FPS HUD Roblox GUI Template with Ammo / Health / Crosshair
A tactical FPS HUD with ammo counter, health bar, crosshair, and kill feed placeholder. Designed for performance-focused first-person shooter experiences on Roblox. Features a dark tactical aesthetic inspired by modern military shooters, with high-contrast UI elements that remain readable during intense gameplay.

Live preview
FPS HUD
1920×1080Includes real, production-ready Luau logic — not a static mockup.
What's inside
- • Ammo / magazine counter
- • Health & armor bars
- • Center crosshair
- • Kill feed placeholder
- • Low-overhead layout
How to use this template
The FPS HUD template shows ammo, health, crosshair, and a kill feed for first-person shooters. Paste the client Luau into StarterGui and the HUD appears, with health bottom-left, ammo bottom-right, and the crosshair centered. The ammo counter updates when the player fires or reloads, and turns red below 25% magazine. The health bar tweens to the new ratio on damage. The crosshair is a small Frame anchored to the screen center. The kill feed is a UIListLayout that fades entries out after 4 seconds. The layout uses Scale-based sizing, so it works on 16:9 and ultrawide. To customize, change the crosshair color and size in the properties panel. Wire the ammo and health updates to your weapon and damage systems. Test in Studio by firing the update events manually and confirming the HUD responds.
Add it to your game in 3 steps
- 1
Copy the Luau
Open the template in the web editor and click Export. Choose LocalScript to copy the full client Luau to your clipboard.
- 2
Paste into StarterGui
In Roblox Studio, right-click StarterGui in the Explorer, insert a LocalScript, and paste the copied Luau. Rename it to match the template.
- 3
Press Play to verify
Click Play in Studio. The GUI should appear exactly as designed. Tweak any Size or Position values in the script if you want to adjust the layout.
1--[[2 FPS HUD - Client LocalScript3 A tactical FPS HUD with ammo counter, health bar, crosshair, and kill feed.4 Place in: StarterPlayer > StarterPlayerScripts5--]]67local Players = game:GetService("Players")8local TweenService = game:GetService("TweenService")9local UserInputService = game:GetService("UserInputService")10local RunService = game:GetService("RunService")11local ReplicatedStorage = game:GetService("ReplicatedStorage")1213local player = Players.LocalPlayer14local playerGui = player:WaitForChild("PlayerGui")1516-- ============================================================17-- REMOTE EVENTS (Created by Server Script)18-- ============================================================19local remotes = ReplicatedStorage:WaitForChild("FPS_HUD_Remotes")20local updateHealthEvent = remotes:WaitForChild("UpdateHealth")21local updateAmmoEvent = remotes:WaitForChild("UpdateAmmo")22local updateScoreEvent = remotes:WaitForChild("UpdateScore")23local killFeedEvent = remotes:WaitForChild("KillFeed")24local hitMarkerEvent = remotes:WaitForChild("HitMarker")25local damageIndicatorEvent = remotes:WaitForChild("DamageIndicator")26local reloadEvent = remotes:WaitForChild("Reload")27local weaponSwitchEvent = remotes:WaitForChild("WeaponSwitch")2829-- ============================================================30-- CONFIGURATION31-- ============================================================32local CONFIG = {33 -- Colors34 CROSSHAIR_COLOR = Color3.fromRGB(0, 255, 100),35 CROSSHAIR_HIT_COLOR = Color3.fromRGB(255, 50, 50),36 HEALTH_HIGH = Color3.fromRGB(0, 255, 100),37 HEALTH_MID = Color3.fromRGB(255, 200, 50),38 HEALTH_LOW = Color3.fromRGB(255, 50, 50),39 AMMO_COLOR = Color3.fromRGB(255, 255, 255),40 AMMO_LOW_COLOR = Color3.fromRGB(255, 100, 100),41 BG_DARK = Color3.fromRGB(20, 20, 20),42 BG_TRANSPARENT = Color3.fromRGB(0, 0, 0),43 TEXT_WHITE = Color3.fromRGB(240, 240, 240),44 TEXT_GRAY = Color3.fromRGB(150, 150, 150),45 HITMARKER_COLOR = Color3.fromRGB(255, 255, 255),46 DAMAGE_COLOR = Color3.fromRGB(255, 0, 0),4748 -- Sizes49 CROSSHAIR_SIZE = 12,50 CROSSHAIR_THICKNESS = 2,51 CROSSHAIR_GAP = 6,52 CROSSHAIR_DOT_SIZE = 2,5354 -- Animation55 TWEEN_INFO_FAST = TweenInfo.new(0.15, Enum.EasingStyle.Quad, Enum.EasingDirection.Out),56 TWEEN_INFO_NORMAL = TweenInfo.new(0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.Out),57 TWEEN_INFO_SLOW = TweenInfo.new(0.5, Enum.EasingStyle.Quad, Enum.EasingDirection.Out),58 HITMARKER_DURATION = 0.2,59 DAMAGE_INDICATOR_DURATION = 0.6,60 KILL_FEED_DURATION = 6,6162 -- Health thresholds63 HEALTH_MID_THRESHOLD = 0.6,64 HEALTH_LOW_THRESHOLD = 0.25,65 AMMO_LOW_THRESHOLD = 0.25,66}6768-- ============================================================69-- STATE70-- ============================================================71local state = {72 health = 100,73 maxHealth = 100,74 ammoCurrent = 30,75 ammoReserve = 120,76 ammoMax = 30,77 score = 0,78 kills = 0,79 deaths = 0,80 isReloading = false,81 currentWeapon = "Assault Rifle",82 crosshairVisible = true,83 hitMarkerTimer = nil,84 damageIndicators = {},85 killFeedItems = {},86}8788-- ============================================================89-- HELPER FUNCTIONS90-- ============================================================9192local function createInstance(className, props)93 local instance = Instance.new(className)94 for key, value in pairs(props) do95n instance[key] = value96 end97 return instance98end99100local function createCorner(parent, radius)101 local corner = Instance.new("UICorner")102 corner.CornerRadius = UDim.new(0, radius or 4)103 corner.Parent = parent104 return corner105end106107local function createGradient(parent, color1, color2, rotation)108 local gradient = Instance.new("UIGradient")109 gradient.Color = ColorSequence.new({110 ColorSequenceKeypoint.new(0, color1 or Color3.new(1, 1, 1)),111 ColorSequenceKeypoint.new(1, color2 or Color3.new(0.5, 0.5, 0.5)),112 })113 gradient.Rotation = rotation or 0114 gradient.Parent = parent115 return gradient116end117118local function lerpColor(a, b, t)119 return Color3.new(120 a.R + (b.R - a.R) * t,121 a.G + (b.G - a.G) * t,122 a.B + (b.B - a.B) * t123 )124end125126local function getHealthColor(ratio)127 if ratio > CONFIG.HEALTH_MID_THRESHOLD then128 local t = (ratio - CONFIG.HEALTH_MID_THRESHOLD) / (1 - CONFIG.HEALTH_MID_THRESHOLD)129 return lerpColor(CONFIG.HEALTH_MID, CONFIG.HEALTH_HIGH, t)130 elseif ratio > CONFIG.HEALTH_LOW_THRESHOLD then131 local t = (ratio - CONFIG.HEALTH_LOW_THRESHOLD) / (CONFIG.HEALTH_MID_THRESHOLD - CONFIG.HEALTH_LOW_THRESHOLD)132 return lerpColor(CONFIG.HEALTH_LOW, CONFIG.HEALTH_MID, t)133 else134 return CONFIG.HEALTH_LOW135 end136end137138-- ============================================================139-- UI CONSTRUCTION140-- ============================================================141142-- Main ScreenGui143local screenGui = createInstance("ScreenGui", {144 Name = "FPS_HUD",145 ResetOnSpawn = false,146 ZIndexBehavior = Enum.ZIndexBehavior.Sibling,147 Parent = playerGui,148})149150-- --------------------------------------------------------151-- CROSSHAIR152-- --------------------------------------------------------153local crosshairContainer = createInstance("Frame", {154 Name = "CrosshairContainer",155 Size = UDim2.fromOffset(40, 40),156 Position = UDim2.fromScale(0.5, 0.5),157 AnchorPoint = Vector2.new(0.5, 0.5),158 BackgroundTransparency = 1,159 ZIndex = 10,160 Parent = screenGui,161})162163local crosshairParts = {}164165-- Top line166local chTop = createInstance("Frame", {167 Name = "Crosshair_Top",168 Size = UDim2.fromOffset(CONFIG.CROSSHAIR_THICKNESS, CONFIG.CROSSHAIR_SIZE),169 Position = UDim2.fromScale(0.5, 0),170 AnchorPoint = Vector2.new(0.5, 1),171 BackgroundColor3 = CONFIG.CROSSHAIR_COLOR,172 BorderSizePixel = 0,173 ZIndex = 10,174 Parent = crosshairContainer,175})176crosshairParts.Top = chTop177178-- Bottom line179local chBottom = createInstance("Frame", {180 Name = "Crosshair_Bottom",181 Size = UDim2.fromOffset(CONFIG.CROSSHAIR_THICKNESS, CONFIG.CROSSHAIR_SIZE),182 Position = UDim2.fromScale(0.5, 1),183 AnchorPoint = Vector2.new(0.5, 0),184 BackgroundColor3 = CONFIG.CROSSHAIR_COLOR,185 BorderSizePixel = 0,186 ZIndex = 10,187 Parent = crosshairContainer,188})189crosshairParts.Bottom = chBottom190191-- Left line192local chLeft = createInstance("Frame", {193 Name = "Crosshair_Left",194 Size = UDim2.fromOffset(CONFIG.CROSSHAIR_SIZE, CONFIG.CROSSHAIR_THICKNESS),195 Position = UDim2.fromScale(0, 0.5),196 AnchorPoint = Vector2.new(1, 0.5),197 BackgroundColor3 = CONFIG.CROSSHAIR_COLOR,198 BorderSizePixel = 0,199 ZIndex = 10,200 Parent = crosshairContainer,201})202crosshairParts.Left = chLeft203204-- Right line205local chRight = createInstance("Frame", {206 Name = "Crosshair_Right",207 Size = UDim2.fromOffset(CONFIG.CROSSHAIR_SIZE, CONFIG.CROSSHAIR_THICKNESS),208 Position = UDim2.fromScale(1, 0.5),209 AnchorPoint = Vector2.new(0, 0.5),210 BackgroundColor3 = CONFIG.CROSSHAIR_COLOR,211 BorderSizePixel = 0,212 ZIndex = 10,213 Parent = crosshairContainer,214})215crosshairParts.Right = chRight216217-- Center dot218local chDot = createInstance("Frame", {219 Name = "Crosshair_Dot",220 Size = UDim2.fromOffset(CONFIG.CROSSHAIR_DOT_SIZE, CONFIG.CROSSHAIR_DOT_SIZE),221 Position = UDim2.fromScale(0.5, 0.5),222 AnchorPoint = Vector2.new(0.5, 0.5),223 BackgroundColor3 = CONFIG.CROSSHAIR_COLOR,224 BorderSizePixel = 0,225 ZIndex = 10,226 Parent = crosshairContainer,227})228crosshairParts.Dot = chDot229230-- --------------------------------------------------------231-- HEALTH BAR232-- --------------------------------------------------------233local healthContainer = createInstance("Frame", {234 Name = "HealthBarContainer",235 Size = UDim2.fromOffset(220, 60),236 Position = UDim2.new(0, 20, 1, -80),237 AnchorPoint = Vector2.new(0, 1),238 BackgroundTransparency = 1,239 ZIndex = 5,240 Parent = screenGui,241})242243local healthLabel = createInstance("TextLabel", {244 Name = "HealthLabel",245 Size = UDim2.fromOffset(40, 20),246 Position = UDim2.fromOffset(0, 0),247 BackgroundTransparency = 1,248 Text = "HP",249 TextColor3 = CONFIG.TEXT_GRAY,250 TextSize = 14,251 Font = Enum.Font.GothamBold,252 TextXAlignment = Enum.TextXAlignment.Left,253 ZIndex = 5,254 Parent = healthContainer,255})256257local healthBarBg = createInstance("Frame", {258 Name = "HealthBarBg",259 Size = UDim2.new(1, 0, 0, 24),260 Position = UDim2.fromOffset(0, 22),261 BackgroundColor3 = CONFIG.BG_DARK,262 BackgroundTransparency = 0.3,263 BorderSizePixel = 0,264 ZIndex = 5,265 Parent = healthContainer,266})267createCorner(healthBarBg, 6)268269local healthBarFill = createInstance("Frame", {270 Name = "HealthBarFill",271 Size = UDim2.fromScale(1, 1),272 BackgroundColor3 = CONFIG.HEALTH_HIGH,273 BorderSizePixel = 0,274 ZIndex = 6,275 Parent = healthBarBg,276})277createCorner(healthBarFill, 6)278279local healthValue = createInstance("TextLabel", {280 Name = "HealthValue",281 Size = UDim2.new(1, 0, 0, 24),282 Position = UDim2.fromOffset(0, 22),283 BackgroundTransparency = 1,284 Text = "100 / 100",285 TextColor3 = CONFIG.TEXT_WHITE,286 TextSize = 14,287 Font = Enum.Font.GothamBold,288 ZIndex = 7,289 Parent = healthContainer,290})291292-- --------------------------------------------------------293-- AMMO COUNTER294-- --------------------------------------------------------295local ammoContainer = createInstance("Frame", {296 Name = "AmmoContainer",297 Size = UDim2.fromOffset(180, 70),298 Position = UDim2.new(1, -20, 1, -90),299 AnchorPoint = Vector2.new(1, 1),300 BackgroundTransparency = 1,301 ZIndex = 5,302 Parent = screenGui,303})304305local ammoCurrent = createInstance("TextLabel", {306 Name = "AmmoCurrent",307 Size = UDim2.fromOffset(70, 50),308 Position = UDim2.new(1, -160, 0, 0),309 BackgroundTransparency = 1,310 Text = tostring(state.ammoCurrent),311 TextColor3 = CONFIG.AMMO_COLOR,312 TextSize = 42,313 Font = Enum.Font.GothamBlack,314 TextXAlignment = Enum.TextXAlignment.Right,315 ZIndex = 5,316 Parent = ammoContainer,317})318319local ammoDivider = createInstance("TextLabel", {320 Name = "AmmoDivider",321 Size = UDim2.fromOffset(20, 40),322 Position = UDim2.new(1, -90, 0, 5),323 BackgroundTransparency = 1,324 Text = "/",325 TextColor3 = CONFIG.TEXT_GRAY,326 TextSize = 28,327 Font = Enum.Font.GothamBold,328 TextXAlignment = Enum.TextXAlignment.Center,329 ZIndex = 5,330 Parent = ammoContainer,331})332333local ammoReserve = createInstance("TextLabel", {334 Name = "AmmoReserve",335 Size = UDim2.fromOffset(70, 40),336 Position = UDim2.new(1, -20, 0, 10),337 AnchorPoint = Vector2.new(1, 0),338 BackgroundTransparency = 1,339 Text = tostring(state.ammoReserve),340 TextColor3 = CONFIG.TEXT_GRAY,341 TextSize = 24,342 Font = Enum.Font.GothamBold,343 TextXAlignment = Enum.TextXAlignment.Left,344 ZIndex = 5,345 Parent = ammoContainer,346})347348local weaponName = createInstance("TextLabel", {349 Name = "WeaponName",350 Size = UDim2.new(1, 0, 0, 18),351 Position = UDim2.fromOffset(0, 52),352 BackgroundTransparency = 1,353 Text = string.upper(state.currentWeapon),354 TextColor3 = CONFIG.TEXT_GRAY,355 TextSize = 11,356 Font = Enum.Font.GothamBold,357 TextXAlignment = Enum.TextXAlignment.Right,358 ZIndex = 5,359 Parent = ammoContainer,360})361362-- --------------------------------------------------------363-- KILL FEED364-- --------------------------------------------------------365local killFeedContainer = createInstance("Frame", {366 Name = "KillFeedContainer",367 Size = UDim2.fromOffset(280, 200),368 Position = UDim2.new(1, -20, 0, 20),369 AnchorPoint = Vector2.new(1, 0),370 BackgroundTransparency = 1,371 ZIndex = 5,372 Parent = screenGui,373})374375local killFeedLayout = createInstance("UIListLayout", {376 SortOrder = Enum.SortOrder.LayoutOrder,377 VerticalAlignment = Enum.VerticalAlignment.Top,378 HorizontalAlignment = Enum.HorizontalAlignment.Right,379 Padding = UDim.new(0, 4),380 Parent = killFeedContainer,381})382383-- --------------------------------------------------------384-- SCORE DISPLAY385-- --------------------------------------------------------386local scoreContainer = createInstance("Frame", {387 Name = "ScoreContainer",388 Size = UDim2.fromOffset(120, 80),389 Position = UDim2.fromOffset(20, 20),390 BackgroundTransparency = 1,391 ZIndex = 5,392 Parent = screenGui,393})394395local scoreLabel = createInstance("TextLabel", {396 Name = "ScoreLabel",397 Size = UDim2.fromOffset(60, 16),398 Position = UDim2.fromOffset(0, 0),399 BackgroundTransparency = 1,400 Text = "SCORE",401 TextColor3 = CONFIG.TEXT_GRAY,402 TextSize = 10,403 Font = Enum.Font.GothamBold,404 TextXAlignment = Enum.TextXAlignment.Left,405 ZIndex = 5,406 Parent = scoreContainer,407})408409local scoreValue = createInstance("TextLabel", {410 Name = "ScoreValue",411 Size = UDim2.fromOffset(60, 26),412 Position = UDim2.fromOffset(0, 16),413 BackgroundTransparency = 1,414 Text = "0",415 TextColor3 = CONFIG.TEXT_WHITE,416 TextSize = 22,417 Font = Enum.Font.GothamBlack,418 TextXAlignment = Enum.TextXAlignment.Left,419 ZIndex = 5,420 Parent = scoreContainer,421})422423local killsLabel = createInstance("TextLabel", {424 Name = "KillsLabel",425 Size = UDim2.fromOffset(50, 16),426 Position = UDim2.fromOffset(0, 44),427 BackgroundTransparency = 1,428 Text = "KILLS",429 TextColor3 = CONFIG.TEXT_GRAY,430 TextSize = 10,431 Font = Enum.Font.GothamBold,432 TextXAlignment = Enum.TextXAlignment.Left,433 ZIndex = 5,434 Parent = scoreContainer,435})436437local killsValue = createInstance("TextLabel", {438 Name = "KillsValue",439 Size = UDim2.fromOffset(50, 20),440 Position = UDim2.fromOffset(50, 44),441 BackgroundTransparency = 1,442 Text = "0",443 TextColor3 = CONFIG.TEXT_WHITE,444 TextSize = 14,445 Font = Enum.Font.GothamBold,446 TextXAlignment = Enum.TextXAlignment.Left,447 ZIndex = 5,448 Parent = scoreContainer,449})450451local deathsLabel = createInstance("TextLabel", {452 Name = "DeathsLabel",453 Size = UDim2.fromOffset(50, 16),454 Position = UDim2.fromOffset(0, 62),455 BackgroundTransparency = 1,456 Text = "DEATHS",457 TextColor3 = CONFIG.TEXT_GRAY,458 TextSize = 10,459 Font = Enum.Font.GothamBold,460 TextXAlignment = Enum.TextXAlignment.Left,461 ZIndex = 5,462 Parent = scoreContainer,463})464465local deathsValue = createInstance("TextLabel", {466 Name = "DeathsValue",467 Size = UDim2.fromOffset(50, 20),468 Position = UDim2.fromOffset(50, 62),469 BackgroundTransparency = 1,470 Text = "0",471 TextColor3 = CONFIG.TEXT_WHITE,472 TextSize = 14,473 Font = Enum.Font.GothamBold,474 TextXAlignment = Enum.TextXAlignment.Left,475 ZIndex = 5,476 Parent = scoreContainer,477})478479-- --------------------------------------------------------480-- HIT MARKER481-- --------------------------------------------------------482local hitMarker = createInstance("Frame", {483 Name = "HitMarker",484 Size = UDim2.fromOffset(24, 24),485 Position = UDim2.fromScale(0.5, 0.5),486 AnchorPoint = Vector2.new(0.5, 0.5),487 BackgroundTransparency = 1,488 ZIndex = 15,489 Parent = screenGui,490 Visible = false,491})492493local hitParts = {}494local hitConfigs = {495 { name = "Hit_TL", pos = UDim2.fromScale(0, 0), anchor = Vector2.new(1, 1), size = UDim2.fromOffset(6, 2), rot = -45 },496 { name = "Hit_TR", pos = UDim2.fromScale(1, 0), anchor = Vector2.new(0, 1), size = UDim2.fromOffset(6, 2), rot = 45 },497 { name = "Hit_BL", pos = UDim2.fromScale(0, 1), anchor = Vector2.new(1, 0), size = UDim2.fromOffset(6, 2), rot = 45 },498 { name = "Hit_BR", pos = UDim2.fromScale(1, 1), anchor = Vector2.new(0, 0), size = UDim2.fromOffset(6, 2), rot = -45 },499}500501for _, cfg in ipairs(hitConfigs) do502 local part = createInstance("Frame", {503 Name = cfg.name,504 Size = cfg.size,505 Position = cfg.pos,506 AnchorPoint = cfg.anchor,507 BackgroundColor3 = CONFIG.HITMARKER_COLOR,508 BorderSizePixel = 0,509 Rotation = cfg.rot,510 ZIndex = 15,511 Parent = hitMarker,512 })513 table.insert(hitParts, part)514end515516-- --------------------------------------------------------517-- DAMAGE INDICATOR (Directional blood overlay)518-- --------------------------------------------------------519local damageIndicator = createInstance("Frame", {520 Name = "DamageIndicator",521 Size = UDim2.fromScale(1, 1),522 Position = UDim2.fromScale(0.5, 0.5),523 AnchorPoint = Vector2.new(0.5, 0.5),524 BackgroundTransparency = 1,525 ZIndex = 8,526 Parent = screenGui,527 Visible = false,528})529530local damageParts = {}531local damageConfigs = {532 { name = "Damage_Top", pos = UDim2.new(0.35, 0, 0, 0), size = UDim2.new(0.3, 0, 0, 80), anchor = Vector2.new(0, 0) },533 { name = "Damage_Bottom", pos = UDim2.new(0.35, 0, 1, 0), size = UDim2.new(0.3, 0, 0, 80), anchor = Vector2.new(0, 1) },534 { name = "Damage_Left", pos = UDim2.new(0, 0, 0.35, 0), size = UDim2.new(0, 80, 0.3, 0), anchor = Vector2.new(0, 0) },535 { name = "Damage_Right", pos = UDim2.new(1, 0, 0.35, 0), size = UDim2.new(0, 80, 0.3, 0), anchor = Vector2.new(1, 0) },536}537538for _, cfg in ipairs(damageConfigs) do539 local part = createInstance("Frame", {540 Name = cfg.name,541 Size = cfg.size,542 Position = cfg.pos,543 AnchorPoint = cfg.anchor,544 BackgroundColor3 = CONFIG.DAMAGE_COLOR,545 BackgroundTransparency = 1,546 BorderSizePixel = 0,547 ZIndex = 8,548 Parent = damageIndicator,549 })550 local grad = createGradient(part, CONFIG.DAMAGE_COLOR, Color3.new(0, 0, 0), 90)551 table.insert(damageParts, { frame = part, gradient = grad })552end553554-- --------------------------------------------------------555-- RELOAD BAR556-- --------------------------------------------------------557local reloadContainer = createInstance("Frame", {558 Name = "ReloadBarContainer",559 Size = UDim2.fromOffset(200, 30),560 Position = UDim2.new(0.5, 0, 1, -130),561 AnchorPoint = Vector2.new(0.5, 1),562 BackgroundTransparency = 1,563 ZIndex = 6,564 Parent = screenGui,565 Visible = false,566})567568local reloadBarBg = createInstance("Frame", {569 Name = "ReloadBarBg",570 Size = UDim2.new(1, 0, 0, 8),571 Position = UDim2.fromScale(0.5, 0.5),572 AnchorPoint = Vector2.new(0.5, 0.5),573 BackgroundColor3 = CONFIG.BG_DARK,574 BackgroundTransparency = 0.5,575 BorderSizePixel = 0,576 ZIndex = 6,577 Parent = reloadContainer,578})579createCorner(reloadBarBg, 4)580581local reloadBarFill = createInstance("Frame", {582 Name = "ReloadBarFill",583 Size = UDim2.fromScale(0, 1),584 BackgroundColor3 = CONFIG.HEALTH_HIGH,585 BorderSizePixel = 0,586 ZIndex = 7,587 Parent = reloadBarBg,588})589createCorner(reloadBarFill, 4)590591local reloadLabel = createInstance("TextLabel", {592 Name = "ReloadLabel",593 Size = UDim2.new(1, 0, 0, 20),594 Position = UDim2.fromOffset(0, -12),595 BackgroundTransparency = 1,596 Text = "RELOADING...",597 TextColor3 = CONFIG.TEXT_GRAY,598 TextSize = 10,599 Font = Enum.Font.GothamBold,600 ZIndex = 7,601 Parent = reloadContainer,602})603604-- --------------------------------------------------------605-- WEAPON SLOTS606-- --------------------------------------------------------607local weaponSlots = createInstance("Frame", {608 Name = "WeaponSlots",609 Size = UDim2.fromOffset(200, 30),610 Position = UDim2.new(0.5, 0, 1, -40),611 AnchorPoint = Vector2.new(0.5, 1),612 BackgroundTransparency = 1,613 ZIndex = 5,614 Parent = screenGui,615})616617local slotLayout = createInstance("UIListLayout", {618 FillDirection = Enum.FillDirection.Horizontal,619 HorizontalAlignment = Enum.HorizontalAlignment.Center,620 VerticalAlignment = Enum.VerticalAlignment.Center,621 Padding = UDim.new(0, 8),622 Parent = weaponSlots,623})624625local slot1 = createInstance("TextButton", {626 Name = "Slot1",627 Size = UDim2.fromOffset(90, 28),628 BackgroundColor3 = CONFIG.BG_DARK,629 BackgroundTransparency = 0.3,630 Text = "1 RIFLE",631 TextColor3 = CONFIG.TEXT_WHITE,632 TextSize = 11,633 Font = Enum.Font.GothamBold,634 BorderSizePixel = 0,635 ZIndex = 5,636 Parent = weaponSlots,637})638createCorner(slot1, 4)639640local slot2 = createInstance("TextButton", {641 Name = "Slot2",642 Size = UDim2.fromOffset(90, 28),643 BackgroundColor3 = CONFIG.BG_DARK,644 BackgroundTransparency = 0.7,645 Text = "2 PISTOL",646 TextColor3 = CONFIG.TEXT_GRAY,647 TextSize = 11,648 Font = Enum.Font.GothamBold,649 BorderSizePixel = 0,650 ZIndex = 5,651 Parent = weaponSlots,652})653createCorner(slot2, 4)654655-- ============================================================656-- UPDATE FUNCTIONS657-- ============================================================658659local function updateHealth(current, max)660 state.health = current661 state.maxHealth = max662 local ratio = math.clamp(current / max, 0, 1)663664 -- Update fill width665 local tween = TweenService:Create(healthBarFill, CONFIG.TWEEN_INFO_NORMAL, {666 Size = UDim2.fromScale(ratio, 1),667 })668 tween:Play()669670 -- Update color based on health level671 local targetColor = getHealthColor(ratio)672 local colorTween = TweenService:Create(healthBarFill, CONFIG.TWEEN_INFO_NORMAL, {673 BackgroundColor3 = targetColor,674 })675 colorTween:Play()676677 -- Update text678 healthValue.Text = string.format("%d / %d", current, max)679680 -- Pulse animation on low health681 if ratio <= CONFIG.HEALTH_LOW_THRESHOLD then682 local pulseTween = TweenService:Create(healthBarFill, TweenInfo.new(0.5, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, -1, true), {683 BackgroundColor3 = CONFIG.HEALTH_LOW,684 })685 pulseTween:Play()686 end687end688689local function updateAmmo(current, reserve)690 state.ammoCurrent = current691 state.ammoReserve = reserve692693 -- Animate current ammo change694 local currentTween = TweenService:Create(ammoCurrent, CONFIG.TWEEN_INFO_FAST, {695 TextTransparency = 0,696 })697 currentTween:Play()698 ammoCurrent.Text = tostring(current)699700 -- Change color when low on ammo701 local ammoRatio = current / state.ammoMax702 if ammoRatio <= CONFIG.AMMO_LOW_THRESHOLD then703 ammoCurrent.TextColor3 = CONFIG.AMMO_LOW_COLOR704 else705 ammoCurrent.TextColor3 = CONFIG.AMMO_COLOR706 end707708 ammoReserve.Text = tostring(reserve)709end710711local function updateScore(score, kills, deaths)712 state.score = score713 state.kills = kills714 state.deaths = deaths715716 scoreValue.Text = tostring(score)717 killsValue.Text = tostring(kills)718 deathsValue.Text = tostring(deaths)719720 -- Pop animation for score721 local popIn = TweenService:Create(scoreValue, TweenInfo.new(0.1, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {722 TextSize = 26,723 })724 local popOut = TweenService:Create(scoreValue, TweenInfo.new(0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {725 TextSize = 22,726 })727 popIn:Play()728 popIn.Completed:Connect(function()729 popOut:Play()730 end)731end732733local function addKillFeedItem(killer, victim, weapon)734 local item = createInstance("Frame", {735 Name = "KillFeedItem",736 Size = UDim2.fromOffset(260, 22),737 BackgroundColor3 = CONFIG.BG_DARK,738 BackgroundTransparency = 0.4,739 BorderSizePixel = 0,740 LayoutOrder = -(#state.killFeedItems),741 ZIndex = 5,742 Parent = killFeedContainer,743 })744 createCorner(item, 3)745746 local text = createInstance("TextLabel", {747 Name = "KillFeedText",748 Size = UDim2.new(1, -8, 1, 0),749 Position = UDim2.fromOffset(4, 0),750 BackgroundTransparency = 1,751 Text = string.format("%s [X] %s", killer, victim),752 TextColor3 = CONFIG.TEXT_WHITE,753 TextSize = 12,754 Font = Enum.Font.GothamBold,755 TextXAlignment = Enum.TextXAlignment.Right,756 ZIndex = 5,757 Parent = item,758 })759760 -- Entry animation761 item.BackgroundTransparency = 1762 text.TextTransparency = 1763 local fadeIn = TweenService:Create(item, CONFIG.TWEEN_INFO_FAST, { BackgroundTransparency = 0.4 })764 local textIn = TweenService:Create(text, CONFIG.TWEEN_INFO_FAST, { TextTransparency = 0 })765 fadeIn:Play()766 textIn:Play()767768 table.insert(state.killFeedItems, 1, item)769770 -- Remove after duration771 task.delay(CONFIG.KILL_FEED_DURATION, function()772 local fadeOut = TweenService:Create(item, CONFIG.TWEEN_INFO_NORMAL, {773 BackgroundTransparency = 1,774 })775 local textOut = TweenService:Create(text, CONFIG.TWEEN_INFO_NORMAL, {776 TextTransparency = 1,777 })778 fadeOut:Play()779 textOut:Play()780 fadeOut.Completed:Wait()781 if item and item.Parent then782 item:Destroy()783 end784 -- Remove from table785 for i, v in ipairs(state.killFeedItems) do786 if v == item then787 table.remove(state.killFeedItems, i)788 break789 end790 end791 end)792793 -- Limit to 5 items794 if #state.killFeedItems > 5 then795 local old = table.remove(state.killFeedItems, 6)796 if old and old.Parent then797 old:Destroy()798 end799 end800end801802local function showHitMarker()803 hitMarker.Visible = true804 for _, part in ipairs(hitParts) do805 part.BackgroundTransparency = 0806 end807808 -- Cancel existing timer809 if state.hitMarkerTimer then810 state.hitMarkerTimer:Disconnect()811 end812813 -- Flash animation814 for _, part in ipairs(hitParts) do815 TweenService:Create(part, TweenInfo.new(0.05), {816 BackgroundColor3 = CONFIG.CROSSHAIR_HIT_COLOR,817 }):Play()818 end819820 task.delay(0.05, function()821 for _, part in ipairs(hitParts) do822 TweenService:Create(part, TweenInfo.new(CONFIG.HITMARKER_DURATION), {823 BackgroundColor3 = CONFIG.HITMARKER_COLOR,824 BackgroundTransparency = 1,825 }):Play()826 end827 end)828829 state.hitMarkerTimer = task.delay(CONFIG.HITMARKER_DURATION + 0.05, function()830 hitMarker.Visible = false831 state.hitMarkerTimer = nil832 end)833end834835local function showDamageIndicator(direction)836 damageIndicator.Visible = true837838 local dirMap = { Top = 1, Bottom = 2, Left = 3, Right = 4 }839 local index = dirMap[direction] or 1840 local partData = damageParts[index]841842 if partData then843 -- Flash the directional indicator844 TweenService:Create(partData.frame, TweenInfo.new(0.1), {845 BackgroundTransparency = 0.3,846 }):Play()847848 task.delay(CONFIG.DAMAGE_INDICATOR_DURATION, function()849 TweenService:Create(partData.frame, TweenInfo.new(0.3), {850 BackgroundTransparency = 1,851 }):Play()852 end)853 end854855 -- Hide container after all fade out856 task.delay(CONFIG.DAMAGE_INDICATOR_DURATION + 0.4, function()857 damageIndicator.Visible = false858 end)859end860861local function startReload(duration)862 state.isReloading = true863 reloadContainer.Visible = true864 reloadBarFill.Size = UDim2.fromScale(0, 1)865866 local tween = TweenService:Create(reloadBarFill, TweenInfo.new(duration, Enum.EasingStyle.Linear), {867 Size = UDim2.fromScale(1, 1),868 })869 tween:Play()870871 tween.Completed:Connect(function()872 state.isReloading = false873 reloadContainer.Visible = false874 end)875end876877local function switchWeapon(slot, weaponName)878 state.currentWeapon = weaponName879 weaponNameLabel.Text = string.upper(weaponName)880881 if slot == 1 then882 TweenService:Create(slot1, CONFIG.TWEEN_INFO_FAST, {883 BackgroundTransparency = 0.3,884 TextColor3 = CONFIG.TEXT_WHITE,885 }):Play()886 TweenService:Create(slot2, CONFIG.TWEEN_INFO_FAST, {887 BackgroundTransparency = 0.7,888 TextColor3 = CONFIG.TEXT_GRAY,889 }):Play()890 elseif slot == 2 then891 TweenService:Create(slot1, CONFIG.TWEEN_INFO_FAST, {892 BackgroundTransparency = 0.7,893 TextColor3 = CONFIG.TEXT_GRAY,894 }):Play()895 TweenService:Create(slot2, CONFIG.TWEEN_INFO_FAST, {896 BackgroundTransparency = 0.3,897 TextColor3 = CONFIG.TEXT_WHITE,898 }):Play()899 end900end901902-- ============================================================903-- CROSSHAIR DYNAMICS (Weapon sway and spread simulation)904-- ============================================================905906local lastMousePos = Vector2.new(0, 0)907local crosshairVelocity = Vector2.new(0, 0)908local spreadScale = 0909910RunService.RenderStepped:Connect(function(deltaTime)911 local mousePos = UserInputService:GetMouseLocation()912 local delta = mousePos - lastMousePos913 crosshairVelocity = crosshairVelocity:Lerp(delta, 0.3)914 lastMousePos = mousePos915916 -- Increase crosshair gap based on movement speed917 local speed = crosshairVelocity.Magnitude918 local targetSpread = math.clamp(speed * 0.15, 0, 10)919 spreadScale = spreadScale + (targetSpread - spreadScale) * 0.1920921 local gap = CONFIG.CROSSHAIR_GAP + spreadScale922 local size = CONFIG.CROSSHAIR_SIZE923924 -- Update crosshair positions925 chTop.Size = UDim2.fromOffset(CONFIG.CROSSHAIR_THICKNESS, size)926 chTop.Position = UDim2.new(0.5, 0, 0, -gap)927 chTop.AnchorPoint = Vector2.new(0.5, 1)928929 chBottom.Size = UDim2.fromOffset(CONFIG.CROSSHAIR_THICKNESS, size)930 chBottom.Position = UDim2.new(0.5, 0, 1, gap)931 chBottom.AnchorPoint = Vector2.new(0.5, 0)932933 chLeft.Size = UDim2.fromOffset(size, CONFIG.CROSSHAIR_THICKNESS)934 chLeft.Position = UDim2.new(0, -gap, 0.5, 0)935 chLeft.AnchorPoint = Vector2.new(1, 0.5)936937 chRight.Size = UDim2.fromOffset(size, CONFIG.CROSSHAIR_THICKNESS)938 chRight.Position = UDim2.new(1, gap, 0.5, 0)939 chRight.AnchorPoint = Vector2.new(0, 0.5)940end)941942-- ============================================================943-- REMOTE EVENT CONNECTIONS944-- ============================================================945946updateHealthEvent.OnClientEvent:Connect(function(current, max)947 updateHealth(current, max)948end)949950updateAmmoEvent.OnClientEvent:Connect(function(current, reserve)951 updateAmmo(current, reserve)952end)953954updateScoreEvent.OnClientEvent:Connect(function(score, kills, deaths)955 updateScore(score, kills, deaths)956end)957958killFeedEvent.OnClientEvent:Connect(function(killer, victim, weapon)959 addKillFeedItem(killer, victim, weapon)960end)961962hitMarkerEvent.OnClientEvent:Connect(function()963 showHitMarker()964end)965966damageIndicatorEvent.OnClientEvent:Connect(function(direction)967 showDamageIndicator(direction)968end)969970reloadEvent.OnClientEvent:Connect(function(duration)971 startReload(duration)972end)973974weaponSwitchEvent.OnClientEvent:Connect(function(slot, weaponName)975 switchWeapon(slot, weaponName)976end)977978-- ============================================================979-- KEYBOARD INPUT (Weapon switching)980-- ============================================================981982UserInputService.InputBegan:Connect(function(input, gameProcessed)983 if gameProcessed then return end984985 if input.KeyCode == Enum.KeyCode.One then986 -- Fire to server to request weapon switch987 local weaponRemote = remotes:WaitForChild("RequestWeaponSwitch")988 weaponRemote:FireServer(1)989 elseif input.KeyCode == Enum.KeyCode.Two then990 local weaponRemote = remotes:WaitForChild("RequestWeaponSwitch")991 weaponRemote:FireServer(2)992 elseif input.KeyCode == Enum.KeyCode.R then993 local reloadRemote = remotes:WaitForChild("RequestReload")994 reloadRemote:FireServer()995 end996end)997998-- ============================================================999-- INITIALIZATION - Demo sequence1000-- ============================================================10011002print("[FPS HUD] Initialized successfully")10031004-- Show intro animation1005task.spawn(function()1006 -- Fade in all containers1007 local containers = { healthContainer, ammoContainer, scoreContainer, weaponSlots }1008 for _, container in ipairs(containers) do1009 container.BackgroundTransparency = 11010 end1011 for _, container in ipairs(containers) do1012 TweenService:Create(container, CONFIG.TWEEN_INFO_SLOW, {1013 BackgroundTransparency = 1,1014 }):Play()1015 task.wait(0.05)1016 end1017end)10181019-- Demo: Simulate some kill feed entries after 2 seconds1020task.delay(2, function()1021 addKillFeedItem("PlayerOne", "Enemy_Soldier", "Rifle")1022 task.wait(1.5)1023 addKillFeedItem("SniperPro", "Enemy_Guard", "Sniper")1024 task.wait(2)1025 addKillFeedItem("You", "Enemy_Boss", "Rifle")1026end)
