-- ═══════════════════════════════════════════════════════════════════ -- MINI CALL OF DUTY - FPS Game Setup (Part 5: Weapon Client Script) -- ═══════════════════════════════════════════════════════════════════ local SG = game:GetService("StarterGui") -- Get the HUD that was already created in Part 4 local hudGui = SG:FindFirstChild("FPS_HUD") -- Add the weapon controller LocalScript local weaponScript = Instance.new("LocalScript") weaponScript.Name = "WeaponController" weaponScript.Parent = hudGui weaponScript.Source = [[ local Players = game:GetService("Players") local RS = game:GetService("ReplicatedStorage") local RunService = game:GetService("RunService") local UIS = game:GetService("UserInputService") local Events = RS:WaitForChild("Events") local Shared = RS:WaitForChild("Shared") local WeaponData = require(Shared:WaitForChild("WeaponData")) local player = Players.LocalPlayer local camera = workspace.CurrentCamera local mouse = player:GetMouse() -- Weapon state local currentWeapon = "M4A1" local weapon = WeaponData[currentWeapon] local ammo = weapon.magSize local reserveAmmo = weapon.maxAmmo local isReloading = false local lastShot = 0 local isADS = false local isSprinting = false local isFiring = false local recoilX = 0 local recoilY = 0 -- UI references local scriptParent = script.Parent local crosshair = scriptParent:WaitForChild("Crosshair") local hitMarker = scriptParent:WaitForChild("HitMarker") local weaponPanel = scriptParent:WaitForChild("WeaponPanel") local ammoLabel = weaponPanel:WaitForChild("AmmoLabel") local weaponLabel = weaponPanel:WaitForChild("WeaponName") local reserveLabel = weaponPanel:WaitForChild("ReserveLabel") local reloadBar = scriptParent:WaitForChild("ReloadBar") local reloadFill = reloadBar:WaitForChild("Fill") local scoreLabel = scriptParent:WaitForChild("ScoreFrame"):WaitForChild("ScoreLabel") local damageVignette = scriptParent:WaitForChild("DamageVignette") local kills = 0 local deaths = 0 local function updateHUD() if ammoLabel then ammoLabel.Text = ammo .. " / " .. reserveAmmo if ammo <= math.floor(weapon.magSize * 0.25) then ammoLabel.TextColor3 = Color3.fromRGB(255, 80, 80) else ammoLabel.TextColor3 = Color3.fromRGB(255, 255, 255) end end if weaponLabel then weaponLabel.Text = weapon.displayName:upper() end if reserveLabel then reserveLabel.Text = isReloading and "RELOADING..." or "" end if scoreLabel then scoreLabel.Text = "KILLS: " .. kills .. " | DEATHS: " .. deaths end end local function shoot() if isReloading then return end if ammo <= 0 then -- Auto reload if reserveAmmo > 0 then -- Play empty click sound via visual feedback end return end if tick() - lastShot < weapon.fireRate then return end lastShot = tick() ammo = ammo - 1 -- Recoil recoilX = recoilX + (math.random() - 0.5) * weapon.recoil.x recoilY = weapon.recoil.y * 0.3 camera.CFrame = camera.CFrame * CFrame.Angles( math.rad(-recoilY), math.rad(recoilX * 0.1), 0 ) -- Spread local spreadAmount = isADS and weapon.spread.ads or weapon.spread.hip local spread = Vector3.new( (math.random() - 0.5) * spreadAmount * 0.01, (math.random() - 0.5) * spreadAmount * 0.01, 0 ) -- Raycast local rayDirection = (camera.CFrame.LookVector + spread) * weapon.range local raycastParams = RaycastParams.new() raycastParams.FilterType = Enum.RaycastFilterType.Exclude local char = player.Character if char then raycastParams.FilterDescendantsInstances = {char} end local result = workspace:Raycast(camera.CFrame.Position, rayDirection, raycastParams) -- Muzzle flash local flash = Instance.new("Part") flash.Size = Vector3.new(0.3, 0.3, 0.3) flash.Shape = Enum.PartType.Ball flash.Color = Color3.fromRGB(255, 200, 50) flash.Material = Enum.Material.Neon flash.Anchored = true flash.CanCollide = false flash.Position = camera.CFrame.Position + camera.CFrame.LookVector * 3 flash.Parent = workspace game:GetService("Debris"):AddItem(flash, 0.04) if result then -- Bullet trail local trail = Instance.new("Part") local trailLen = (camera.CFrame.Position - result.Position).Magnitude trail.Size = Vector3.new(0.08, 0.08, trailLen) trail.CFrame = CFrame.new(camera.CFrame.Position, result.Position) * CFrame.new(0, 0, -trailLen / 2) trail.Anchored = true trail.CanCollide = false trail.Color = Color3.fromRGB(255, 220, 100) trail.Material = Enum.Material.Neon trail.Transparency = 0.4 trail.Parent = workspace game:GetService("Debris"):AddItem(trail, 0.06) -- Impact spark local spark = Instance.new("Part") spark.Size = Vector3.new(0.4, 0.4, 0.4) spark.Shape = Enum.PartType.Ball spark.Color = Color3.fromRGB(255, 180, 50) spark.Material = Enum.Material.Neon spark.Anchored = true spark.CanCollide = false spark.Position = result.Position spark.Parent = workspace game:GetService("Debris"):AddItem(spark, 0.12) -- Smoke puff at impact local smoke = Instance.new("Part") smoke.Size = Vector3.new(1, 1, 1) smoke.Shape = Enum.PartType.Ball smoke.Color = Color3.fromRGB(120, 120, 110) smoke.Transparency = 0.5 smoke.Anchored = true smoke.CanCollide = false smoke.Position = result.Position smoke.Parent = workspace game:GetService("Debris"):AddItem(smoke, 0.3) -- Send to server Events:WaitForChild("ShootEvent"):FireServer({ origin = camera.CFrame.Position, direction = rayDirection, hit = result.Instance, hitPos = result.Position, normal = result.Normal, weapon = currentWeapon, }) else -- Shot into air - just trail to max range local endPoint = camera.CFrame.Position + rayDirection local trail = Instance.new("Part") local trailLen = weapon.range trail.Size = Vector3.new(0.06, 0.06, trailLen) trail.CFrame = CFrame.new(camera.CFrame.Position, endPoint) * CFrame.new(0, 0, -trailLen / 2) trail.Anchored = true trail.CanCollide = false trail.Color = Color3.fromRGB(255, 220, 100) trail.Material = Enum.Material.Neon trail.Transparency = 0.5 trail.Parent = workspace game:GetService("Debris"):AddItem(trail, 0.04) end -- Auto reload when empty if ammo <= 0 and reserveAmmo > 0 then task.delay(0.3, function() reload() end) end updateHUD() end local function reload() if isReloading then return end if ammo >= weapon.magSize then return end if reserveAmmo <= 0 then return end isReloading = true reloadBar.Visible = true local startTime = tick() local conn conn = RunService.RenderStepped:Connect(function() local elapsed = tick() - startTime local pct = math.clamp(elapsed / weapon.reloadTime, 0, 1) reloadFill.Size = UDim2.new(pct * 200, 0, 1, 0) if pct >= 1 then conn:Disconnect() local needed = weapon.magSize - ammo local toLoad = math.min(needed, reserveAmmo) ammo = ammo + toLoad reserveAmmo = reserveAmmo - toLoad isReloading = false reloadBar.Visible = false reloadFill.Size = UDim2.new(0, 0, 1, 0) updateHUD() end end) updateHUD() end -- Input handling UIS.InputBegan:Connect(function(input, processed) if processed then return end if input.UserInputType == Enum.UserInputType.MouseButton2 then isADS = true if isSprinting then isSprinting = false end end if input.UserInputType == Enum.UserInputType.MouseButton1 then isFiring = true if not weapon.automatic then shoot() end if isSprinting then isSprinting = false end end if input.KeyCode == Enum.KeyCode.LeftShift then if not isADS then isSprinting = true end end if input.KeyCode == Enum.KeyCode.LeftControl then local c = player.Character if c then local h = c:FindFirstChildOfClass("Humanoid") if h then h.WalkSpeed = 8 end end end if input.KeyCode == Enum.KeyCode.R then reload() end -- Weapon switch if input.KeyCode == Enum.KeyCode.One then currentWeapon = "M4A1" elseif input.KeyCode == Enum.KeyCode.Two then currentWeapon = "AK47" elseif input.KeyCode == Enum.KeyCode.Three then currentWeapon = "Sniper" elseif input.KeyCode == Enum.KeyCode.Four then currentWeapon = "Shotgun" end if input.KeyCode >= Enum.KeyCode.One and input.KeyCode <= Enum.KeyCode.Four then weapon = WeaponData[currentWeapon] ammo = weapon.magSize reserveAmmo = weapon.maxAmmo isReloading = false reloadBar.Visible = false updateHUD() end end) UIS.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton2 then isADS = false end if input.UserInputType == Enum.UserInputType.MouseButton1 then isFiring = false end if input.KeyCode == Enum.KeyCode.LeftShift then isSprinting = false end if input.KeyCode == Enum.KeyCode.LeftControl then local c = player.Character if c then local h = c:FindFirstChildOfClass("Humanoid") if h then h.WalkSpeed = 20 end end end end) -- Track kills/deaths from events Events:WaitForChild("KillEvent").OnClientEvent:Connect(function(data) if data.killer == player.Name then kills = kills + 1 end if data.victim == player.Name then deaths = deaths + 1 end updateHUD() end) -- Main loop RunService.RenderStepped:Connect(function() -- Camera FOV for ADS local targetFOV = isADS and weapon.adsFOV or 70 camera.FieldOfView = camera.FieldOfView + (targetFOV - camera.FieldOfView) * 0.2 -- Sprint speed local c = player.Character if c then local h = c:FindFirstChildOfClass("Humanoid") if h and h.MoveDirection.Magnitude > 0 then if isSprinting then h.WalkSpeed = 30 elseif not UIS:IsKeyDown(Enum.KeyCode.LeftControl) then h.WalkSpeed = 20 end end end -- Auto-fire for automatic weapons if isFiring and weapon.automatic then shoot() end -- Recoil recovery recoilX = recoilX * 0.9 recoilY = recoilY * 0.85 -- Crosshair spread local spreadPx = isADS and 2 or (isSprinting and 15 or 6) if isFiring then spreadPx = spreadPx + 4 end for _, child in ipairs(crosshair:GetChildren()) do if child.Name == "Top" then child.Position = UDim2.new(0, 9, 0, 9 - spreadPx) elseif child.Name == "Bottom" then child.Position = UDim2.new(0, 9, 0, 9 + spreadPx) elseif child.Name == "Left" then child.Position = UDim2.new(0, 9 - spreadPx, 0, 9) elseif child.Name == "Right" then child.Position = UDim2.new(0, 9 + spreadPx, 0, 9) end end end) -- First person lock UIS.MouseIconEnabled = false player.CameraMode = Enum.CameraMode.LockFirstPerson player.CharacterAdded:Connect(function() ammo = weapon.magSize reserveAmmo = weapon.maxAmmo kills = 0 deaths = 0 isReloading = false reloadBar.Visible = false updateHUD() end) updateHUD() print("═══════════════════════════════════════════") print(" MINI CALL OF DUTY - LOADED!") print(" Controls:") print(" WASD = Move") print(" LMB = Shoot") print(" RMB = Aim Down Sights") print(" Shift = Sprint") print(" Ctrl = Crouch") print(" R = Reload") print(" 1-4 = Switch Weapon") print(" Weapons: M4A1(1), AK-47(2), AWP Sniper(3), SPAS-12(4)") print("═══════════════════════════════════════════") ]] print("[CoD FPS] Part 5/5 complete: Weapon controller script created.") print("═══════════════════════════════════════════") print(" ALL PARTS COMPLETE! Press PLAY in Studio to start.") print("═══════════════════════════════════════════")