- Updated RobloxMCPPlugin with HTTP polling (auto-enables HttpService) - Added 20-weapon FPS game example (CoD-style) - Added Python studio-inject.py for command bar injection via Win32 API - Added auto-connect setup scripts (VBS + PowerShell) - Updated MCP server with all FPS game tools Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
422 lines
14 KiB
Lua
422 lines
14 KiB
Lua
-- ═══════════════════════════════════════════════════════════════════
|
|
-- MINI CALL OF DUTY - FPS Game Setup (Part 4: HUD + Player Scripts)
|
|
-- ═══════════════════════════════════════════════════════════════════
|
|
|
|
local SG = game:GetService("StarterGui")
|
|
local SP = game:GetService("StarterPlayer")
|
|
|
|
-- ═══════════════════════════════════════════════════════════════
|
|
-- HUD (ScreenGui + LocalScript)
|
|
-- ═══════════════════════════════════════════════════════════════
|
|
local hudGui = Instance.new("ScreenGui")
|
|
hudGui.Name = "FPS_HUD"
|
|
hudGui.ResetOnSpawn = false
|
|
hudGui.IgnoreGuiInset = true
|
|
hudGui.Parent = SG
|
|
|
|
-- Crosshair
|
|
local cross = Instance.new("Frame")
|
|
cross.Name = "Crosshair"
|
|
cross.Size = UDim2.new(0, 20, 0, 20)
|
|
cross.Position = UDim2.new(0.5, -10, 0.5, -10)
|
|
cross.BackgroundTransparency = 1
|
|
cross.Parent = hudGui
|
|
|
|
for _, dir in ipairs({{0,-12,0,4,"Top"},{0,4,0,12,"Bottom"},{-12,0,4,0,"Left"},{4,0,12,0,"Right"}}) do
|
|
local line = Instance.new("Frame")
|
|
line.Name = dir[5]
|
|
line.Size = UDim2.new(0, dir[3] == 0 and 2 or dir[3], 0, dir[4] == 0 and 2 or dir[4])
|
|
line.Position = UDim2.new(0, 9+dir[1], 0, 9+dir[2])
|
|
line.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
|
|
line.BackgroundTransparency = 0.2
|
|
line.BorderSizePixel = 0
|
|
line.Parent = cross
|
|
end
|
|
|
|
-- Center dot
|
|
local dot = Instance.new("Frame")
|
|
dot.Name = "CenterDot"
|
|
dot.Size = UDim2.new(0, 3, 0, 3)
|
|
dot.Position = UDim2.new(0, 8, 0, 8)
|
|
dot.BackgroundColor3 = Color3.fromRGB(255, 50, 50)
|
|
dot.BorderSizePixel = 0
|
|
dot.Parent = cross
|
|
|
|
-- Hit marker (appears on hit)
|
|
local hitMarker = Instance.new("Frame")
|
|
hitMarker.Name = "HitMarker"
|
|
hitMarker.Size = UDim2.new(0, 30, 0, 30)
|
|
hitMarker.Position = UDim2.new(0.5, -15, 0.5, -15)
|
|
hitMarker.BackgroundTransparency = 1
|
|
hitMarker.Visible = false
|
|
hitMarker.Parent = hudGui
|
|
|
|
for _, d in ipairs({{-8,-8,6,6,45},{2,-8,6,6,-45},{-8,2,6,6,-45},{2,2,6,6,45}}) do
|
|
local mark = Instance.new("Frame")
|
|
mark.Size = UDim2.new(0, d[3], 0, d[4])
|
|
mark.Position = UDim2.new(0, 12+d[1], 0, 12+d[2])
|
|
mark.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
|
|
mark.BorderSizePixel = 0
|
|
mark.Rotation = d[5]
|
|
mark.Parent = hitMarker
|
|
end
|
|
|
|
-- Damage vignette overlay
|
|
local dmgVignette = Instance.new("Frame")
|
|
dmgVignette.Name = "DamageVignette"
|
|
dmgVignette.Size = UDim2.new(1, 0, 1, 0)
|
|
dmgVignette.BackgroundColor3 = Color3.fromRGB(200, 0, 0)
|
|
dmgVignette.BackgroundTransparency = 1
|
|
dmgVignette.BorderSizePixel = 0
|
|
dmgVignette.ZIndex = 9
|
|
dmgVignette.Parent = hudGui
|
|
|
|
-- Kill feed frame (top right)
|
|
local killFeedFrame = Instance.new("Frame")
|
|
killFeedFrame.Name = "KillFeed"
|
|
killFeedFrame.Size = UDim2.new(0, 350, 0, 150)
|
|
killFeedFrame.Position = UDim2.new(1, -360, 0, 10)
|
|
killFeedFrame.BackgroundTransparency = 1
|
|
killFeedFrame.Parent = hudGui
|
|
|
|
-- Score display (top center)
|
|
local scoreFrame = Instance.new("Frame")
|
|
scoreFrame.Name = "ScoreFrame"
|
|
scoreFrame.Size = UDim2.new(0, 200, 0, 40)
|
|
scoreFrame.Position = UDim2.new(0.5, -100, 0, 10)
|
|
scoreFrame.BackgroundColor3 = Color3.fromRGB(0, 0, 0)
|
|
scoreFrame.BackgroundTransparency = 0.5
|
|
scoreFrame.BorderSizePixel = 0
|
|
scoreFrame.Parent = hudGui
|
|
|
|
local scoreLabel = Instance.new("TextLabel")
|
|
scoreLabel.Name = "ScoreLabel"
|
|
scoreLabel.Size = UDim2.new(1, 0, 1, 0)
|
|
scoreLabel.BackgroundTransparency = 1
|
|
scoreLabel.Text = "KILLS: 0 | DEATHS: 0"
|
|
scoreLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
|
|
scoreLabel.TextSize = 18
|
|
scoreLabel.Font = Enum.Font.GothamBold
|
|
scoreLabel.Parent = scoreFrame
|
|
|
|
-- Killstreak banner (center)
|
|
local streakBanner = Instance.new("TextLabel")
|
|
streakBanner.Name = "StreakBanner"
|
|
streakBanner.Size = UDim2.new(0, 400, 0, 60)
|
|
streakBanner.Position = UDim2.new(0.5, -200, 0.3, 0)
|
|
streakBanner.BackgroundTransparency = 1
|
|
streakBanner.Text = ""
|
|
streakBanner.TextColor3 = Color3.fromRGB(255, 200, 50)
|
|
streakBanner.TextSize = 32
|
|
streakBanner.Font = Enum.Font.GothamBold
|
|
streakBanner.TextStrokeTransparency = 0
|
|
streakBanner.Visible = false
|
|
streakBanner.ZIndex = 10
|
|
streakBanner.Parent = hudGui
|
|
|
|
-- Minimap (top left)
|
|
local minimap = Instance.new("Frame")
|
|
minimap.Name = "Minimap"
|
|
minimap.Size = UDim2.new(0, 150, 0, 150)
|
|
minimap.Position = UDim2.new(0, 10, 0, 10)
|
|
minimap.BackgroundColor3 = Color3.fromRGB(30, 40, 30)
|
|
minimap.BackgroundTransparency = 0.3
|
|
minimap.BorderSizePixel = 0
|
|
minimap.Parent = hudGui
|
|
|
|
local mapCorner = Instance.new("UICorner")
|
|
mapCorner.CornerRadius = UDim.new(0, 75)
|
|
mapCorner.Parent = minimap
|
|
|
|
local playerDot = Instance.new("Frame")
|
|
playerDot.Name = "PlayerDot"
|
|
playerDot.Size = UDim2.new(0, 6, 0, 6)
|
|
playerDot.Position = UDim2.new(0.5, -3, 0.5, -3)
|
|
playerDot.BackgroundColor3 = Color3.fromRGB(0, 255, 0)
|
|
playerDot.BorderSizePixel = 0
|
|
playerDot.Parent = minimap
|
|
|
|
-- Weapon info panel (bottom right)
|
|
local weaponPanel = Instance.new("Frame")
|
|
weaponPanel.Name = "WeaponPanel"
|
|
weaponPanel.Size = UDim2.new(0, 250, 0, 80)
|
|
weaponPanel.Position = UDim2.new(1, -260, 1, -90)
|
|
weaponPanel.BackgroundColor3 = Color3.fromRGB(0, 0, 0)
|
|
weaponPanel.BackgroundTransparency = 0.4
|
|
weaponPanel.BorderSizePixel = 0
|
|
weaponPanel.Parent = hudGui
|
|
|
|
local weaponLabel = Instance.new("TextLabel")
|
|
weaponLabel.Name = "WeaponName"
|
|
weaponLabel.Size = UDim2.new(1, -10, 0, 25)
|
|
weaponLabel.Position = UDim2.new(0, 5, 0, 5)
|
|
weaponLabel.BackgroundTransparency = 1
|
|
weaponLabel.Text = "M4A1 CARBINE"
|
|
weaponLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
|
|
weaponLabel.TextSize = 16
|
|
weaponLabel.Font = Enum.Font.GothamBold
|
|
weaponLabel.TextXAlignment = Enum.TextXAlignment.Right
|
|
weaponLabel.Parent = weaponPanel
|
|
|
|
local ammoLabel = Instance.new("TextLabel")
|
|
ammoLabel.Name = "AmmoLabel"
|
|
ammoLabel.Size = UDim2.new(1, -10, 0, 35)
|
|
ammoLabel.Position = UDim2.new(0, 5, 0, 25)
|
|
ammoLabel.BackgroundTransparency = 1
|
|
ammoLabel.Text = "30 / 210"
|
|
ammoLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
|
|
ammoLabel.TextSize = 28
|
|
ammoLabel.Font = Enum.Font.GothamBold
|
|
ammoLabel.TextXAlignment = Enum.TextXAlignment.Right
|
|
ammoLabel.Parent = weaponPanel
|
|
|
|
local reserveLabel = Instance.new("TextLabel")
|
|
reserveLabel.Name = "ReserveLabel"
|
|
reserveLabel.Size = UDim2.new(1, -10, 0, 15)
|
|
reserveLabel.Position = UDim2.new(0, 5, 0, 60)
|
|
reserveLabel.BackgroundTransparency = 1
|
|
reserveLabel.Text = ""
|
|
reserveLabel.TextColor3 = Color3.fromRGB(180, 180, 180)
|
|
reserveLabel.TextSize = 12
|
|
reserveLabel.Font = Enum.Font.Gotham
|
|
reserveLabel.TextXAlignment = Enum.TextXAlignment.Right
|
|
reserveLabel.Parent = weaponPanel
|
|
|
|
-- Reload bar
|
|
local reloadBar = Instance.new("Frame")
|
|
reloadBar.Name = "ReloadBar"
|
|
reloadBar.Size = UDim2.new(0, 200, 0, 8)
|
|
reloadBar.Position = UDim2.new(0.5, -100, 0.6, 0)
|
|
reloadBar.BackgroundColor3 = Color3.fromRGB(40, 40, 40)
|
|
reloadBar.BorderSizePixel = 0
|
|
reloadBar.Visible = false
|
|
reloadBar.Parent = hudGui
|
|
|
|
local reloadFill = Instance.new("Frame")
|
|
reloadFill.Name = "Fill"
|
|
reloadFill.Size = UDim2.new(0, 0, 1, 0)
|
|
reloadFill.BackgroundColor3 = Color3.fromRGB(255, 200, 50)
|
|
reloadFill.BorderSizePixel = 0
|
|
reloadFill.Parent = reloadBar
|
|
|
|
-- Controls hint (bottom center)
|
|
local controlsHint = Instance.new("TextLabel")
|
|
controlsHint.Name = "Controls"
|
|
controlsHint.Size = UDim2.new(0, 600, 0, 25)
|
|
controlsHint.Position = UDim2.new(0.5, -300, 1, -30)
|
|
controlsHint.BackgroundTransparency = 1
|
|
controlsHint.Text = "WASD=Move | LMB=Shoot | RMB=ADS | Shift=Sprint | Ctrl=Crouch | R=Reload | 1-4=Weapons"
|
|
controlsHint.TextColor3 = Color3.fromRGB(150, 150, 150)
|
|
controlsHint.TextSize = 12
|
|
controlsHint.Font = Enum.Font.Gotham
|
|
controlsHint.Parent = hudGui
|
|
|
|
-- ═══════════════════════════════════════════════════════════════
|
|
-- PLAYER SETUP SCRIPT (LocalScript in StarterPlayerScripts)
|
|
-- ═══════════════════════════════════════════════════════════════
|
|
local spScripts = SP:FindFirstChild("StarterPlayerScripts")
|
|
if not spScripts then
|
|
spScripts = Instance.new("Folder")
|
|
spScripts.Name = "StarterPlayerScripts"
|
|
spScripts.Parent = SP
|
|
end
|
|
|
|
local playerSetup = Instance.new("LocalScript")
|
|
playerSetup.Name = "PlayerSetup"
|
|
playerSetup.Parent = spScripts
|
|
playerSetup.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 player = Players.LocalPlayer
|
|
local camera = workspace.CurrentCamera
|
|
|
|
-- Force first person
|
|
player.CameraMode = Enum.CameraMode.LockFirstPerson
|
|
player.CameraMaxZoomDistance = 0.5
|
|
player.CameraMinZoomDistance = 0.5
|
|
|
|
-- Character setup on spawn
|
|
player.CharacterAdded:Connect(function(char)
|
|
task.wait(0.5)
|
|
local hum = char:WaitForChild("Humanoid")
|
|
hum.WalkSpeed = 20
|
|
hum.JumpPower = 40
|
|
|
|
-- Health regen
|
|
task.spawn(function()
|
|
while hum and hum.Health > 0 do
|
|
task.wait(2)
|
|
if hum.Health < hum.MaxHealth and hum.Health > 0 then
|
|
hum.Health = math.min(hum.MaxHealth, hum.Health + 3)
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- Damage vignette on hit
|
|
hum.HealthChanged:Connect(function(health)
|
|
local lost = hum.MaxHealth - health
|
|
if lost > 0 then
|
|
local gui = player:FindFirstChild("PlayerGui")
|
|
if gui then
|
|
local hud = gui:FindFirstChild("FPS_HUD")
|
|
if hud then
|
|
local vignette = hud:FindFirstChild("DamageVignette")
|
|
if vignette then
|
|
local intensity = math.clamp(lost / hum.MaxHealth, 0, 0.6)
|
|
vignette.BackgroundTransparency = 1 - intensity
|
|
task.delay(0.3, function()
|
|
if vignette then
|
|
vignette.BackgroundTransparency = 1
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
end)
|
|
|
|
-- Kill feed listener
|
|
Events:WaitForChild("KillEvent").OnClientEvent:Connect(function(data)
|
|
local gui = player:FindFirstChild("PlayerGui")
|
|
if not gui then return end
|
|
local hud = gui:FindFirstChild("FPS_HUD")
|
|
if not hud then return end
|
|
local feed = hud:FindFirstChild("KillFeed")
|
|
if not feed then return end
|
|
|
|
-- Create kill feed entry
|
|
local entry = Instance.new("TextLabel")
|
|
entry.Size = UDim2.new(1, 0, 0, 25)
|
|
entry.BackgroundTransparency = 0.4
|
|
entry.BackgroundColor3 = Color3.fromRGB(0, 0, 0)
|
|
entry.Text = " " .. data.killer .. " [" .. data.weapon .. "] " .. data.victim
|
|
.. (data.headshot and " ★" or "")
|
|
entry.TextColor3 = data.killer == player.Name and Color3.fromRGB(50, 255, 50)
|
|
or Color3.fromRGB(255, 255, 255)
|
|
entry.TextSize = 14
|
|
entry.Font = Enum.Font.GothamBold
|
|
entry.TextXAlignment = Enum.TextXAlignment.Right
|
|
entry.BorderSizePixel = 0
|
|
|
|
-- Headshot indicator color
|
|
if data.headshot then
|
|
entry.TextColor3 = Color3.fromRGB(255, 50, 50)
|
|
end
|
|
|
|
entry.Parent = feed
|
|
|
|
-- Shift older entries down
|
|
for i, child in ipairs(feed:GetChildren()) do
|
|
if child:IsA("TextLabel") then
|
|
child.Position = UDim2.new(0, 0, 0, (i-1) * 28)
|
|
end
|
|
end
|
|
|
|
-- Remove after 5 seconds
|
|
task.delay(5, function()
|
|
if entry then entry:Destroy() end
|
|
end)
|
|
|
|
-- Killstreak banner
|
|
if data.killer == player.Name and data.streak then
|
|
local banner = hud:FindFirstChild("StreakBanner")
|
|
if banner then
|
|
local streakNames = {
|
|
[3] = "TRIPLE KILL!",
|
|
[5] = "KILLING SPREE!",
|
|
[7] = "UNSTOPPABLE!",
|
|
[10] = "TACTICAL NUKE READY!",
|
|
}
|
|
local msg = streakNames[data.streak]
|
|
if msg then
|
|
banner.Text = msg
|
|
banner.Visible = true
|
|
task.delay(3, function()
|
|
if banner then banner.Visible = false end
|
|
end)
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- Hit marker listener
|
|
Events:WaitForChild("DamageEvent").OnClientEvent:Connect(function(data)
|
|
local gui = player:FindFirstChild("PlayerGui")
|
|
if not gui then return end
|
|
local hud = gui:FindFirstChild("FPS_HUD")
|
|
if not hud then return end
|
|
|
|
-- Show hit marker
|
|
local hm = hud:FindFirstChild("HitMarker")
|
|
if hm and data.hit then
|
|
hm.Visible = true
|
|
-- Change color for headshots
|
|
for _, child in ipairs(hm:GetChildren()) do
|
|
if child:IsA("Frame") then
|
|
child.BackgroundColor3 = data.headshot
|
|
and Color3.fromRGB(255, 50, 50)
|
|
or Color3.fromRGB(255, 255, 255)
|
|
end
|
|
end
|
|
task.delay(0.15, function()
|
|
if hm then hm.Visible = false end
|
|
end)
|
|
end
|
|
end)
|
|
|
|
-- Minimap updater
|
|
task.spawn(function()
|
|
task.wait(3)
|
|
while true do
|
|
task.wait(0.5)
|
|
local char = player.Character
|
|
if char then
|
|
local gui = player:FindFirstChild("PlayerGui")
|
|
if gui then
|
|
local hud = gui:FindFirstChild("FPS_HUD")
|
|
if hud then
|
|
local map = hud:FindFirstChild("Minimap")
|
|
if map then
|
|
-- Update enemy dots
|
|
for _, child in ipairs(map:GetChildren()) do
|
|
if child.Name == "EnemyDot" then child:Destroy() end
|
|
end
|
|
for _, obj in ipairs(workspace:GetChildren()) do
|
|
if obj.Name:match("^Enemy_") then
|
|
local hum = obj:FindFirstChildOfClass("Humanoid")
|
|
if hum and hum.Health > 0 then
|
|
local root = obj:FindFirstChild("HumanoidRootPart")
|
|
if root and char:FindFirstChild("Head") then
|
|
local relPos = root.Position - char.Head.Position
|
|
local mapScale = 150 / 400 -- minimap size / map size
|
|
local mx = math.clamp(relPos.X * mapScale + 72, 5, 145)
|
|
local mz = math.clamp(relPos.Z * mapScale + 72, 5, 145)
|
|
|
|
local eDot = Instance.new("Frame")
|
|
eDot.Name = "EnemyDot"
|
|
eDot.Size = UDim2.new(0, 5, 0, 5)
|
|
eDot.Position = UDim2.new(0, mx, 0, mz)
|
|
eDot.BackgroundColor3 = Color3.fromRGB(255, 50, 50)
|
|
eDot.BorderSizePixel = 0
|
|
eDot.Parent = map
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
print("[PlayerSetup] FPS player configured.)
|
|
]]
|
|
|
|
print("[CoD FPS] Part 4/5 complete: HUD + Player scripts created.")
|