
Keyless

-- ╔══════════════════════════════════════════════════════╗
-- ║ PTFS AUTOPILOT v15 — FULL REWRITE ║
-- ║ Custom UI • Kokpit HUD • AP Menü Ayrı ║
-- ╚══════════════════════════════════════════════════════╝
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UIS = game:GetService("UserInputService")
local TweenS = game:GetService("TweenService")
local Player = Players.LocalPlayer
local PlayerGui = Player:WaitForChild("PlayerGui")
-- Eski gui temizle
for _, name in ipairs({"PTFSMain","PTFSCockpit"}) do
if PlayerGui:FindFirstChild(name) then PlayerGui[name]:Destroy() end
end
-- ════════════════════════════════════════════════════════
-- KOORDİNATLAR
-- ════════════════════════════════════════════════════════
local Airports = {
{ name="Greater Rockford", runways={
{ name="07R", threshold=Vector3.new(-3481.3,3.3,20699.9), heading=292.9 },
{ name="25L", threshold=Vector3.new(-2726.9,3.3,20379.7), heading=112.9 },
}},
{ name="Saint Barthelemy", runways={
{ name="09", threshold=Vector3.new(5470.4,11.5,-4485.6), heading=1.5 },
{ name="27", threshold=Vector3.new(5950.7,3.1,-4485.8), heading=256.5 },
}},
{ name="Tokyo International", runways={
{ name="20", threshold=Vector3.new(-6921.5,21.5,-30891.2),heading=340.1 },
{ name="02", threshold=Vector3.new(-6399.0,21.5,-32326.8),heading=160.2 },
}},
}
-- ════════════════════════════════════════════════════════
-- AUTOPILOT STATE
-- ════════════════════════════════════════════════════════
local AP = {
active = false,
phase = "IDLE",
depRunway = nil,
arrRunway = nil,
aircraft = nil,
rootPart = nil,
CRUISE_ALT = 2000,
CRUISE_SPD = 350,
TAKEOFF_SPD = 280,
LANDING_SPD = 110,
CLIMB_PITCH = 15,
}
local waypoints, wpIndex = {}, 1
local bvel, bgyro = nil, nil
local spd = 0
local hbConn = nil
-- ════════════════════════════════════════════════════════
-- YARDIMCILAR
-- ════════════════════════════════════════════════════════
local function headingDir(deg)
local r = math.rad(deg)
return Vector3.new(math.sin(r), 0, math.cos(r))
end
local function dist2D(a, b)
return Vector3.new(a.X-b.X, 0, a.Z-b.Z).Magnitude
end
local function pressKey(key)
pcall(function()
local VIM = game:GetService("VirtualInputManager")
VIM:SendKeyEvent(true, Enum.KeyCode[key], false, game)
task.wait(0.1)
VIM:SendKeyEvent(false, Enum.KeyCode[key], false, game)
end)
end
local function fly(vel, lookDir)
if bvel and bvel.Parent then bvel.Velocity = vel end
if bgyro and bgyro.Parent then
if lookDir.Magnitude > 0.001 then
bgyro.CFrame = CFrame.new(Vector3.new(), lookDir.Unit)
end
end
end
local function getAlt() return AP.rootPart and AP.rootPart.Position.Y or 0 end
-- ════════════════════════════════════════════════════════
-- WAYPOINT & AP MANTIK
-- ════════════════════════════════════════════════════════
local function buildWaypoints()
waypoints = {}
wpIndex = 1
local dep = AP.depRunway
local arr = AP.arrRunway
local alt = AP.CRUISE_ALT
local depDir = headingDir(dep.heading)
local arrDir = headingDir(arr.heading)
local climbOut = dep.threshold + depDir * 3000
climbOut = Vector3.new(climbOut.X, alt, climbOut.Z)
local finalLeg = arr.threshold - arrDir * 12000
finalLeg = Vector3.new(finalLeg.X, alt, finalLeg.Z)
local descentStart= arr.threshold - arrDir * 5000
descentStart = Vector3.new(descentStart.X, alt, descentStart.Z)
table.insert(waypoints, { pos=climbOut, onArrive=function() spd=AP.CRUISE_SPD end })
table.insert(waypoints, { pos=finalLeg, onArrive=function() end })
table.insert(waypoints, { pos=descentStart, onArrive=function()
AP.phase = "APPROACH"; spd = AP.LANDING_SPD
task.spawn(function() pressKey("F"); task.wait(0.3); pressKey("G") end)
end})
end
local function stopAP(reason)
AP.active = false; AP.phase = "IDLE"
if hbConn then hbConn:Disconnect(); hbConn = nil end
if bvel and bvel.Parent then bvel:Destroy(); bvel = nil end
if bgyro and bgyro.Parent then bgyro:Destroy(); bgyro = nil end
print("⏹️ AP: " .. (reason or "Manuel"))
end
local function startLoop()
spd = 0; wpIndex = 1
if hbConn then hbConn:Disconnect() end
hbConn = RunService.Heartbeat:Connect(function(dt)
if not AP.active then hbConn:Disconnect(); hbConn = nil; return end
if not AP.rootPart or not AP.rootPart.Parent then
local char = Player.Character
if char then
local hum = char:FindFirstChildOfClass("Humanoid")
if hum and hum.SeatPart then
AP.aircraft = hum.SeatPart.Parent
AP.rootPart = AP.aircraft:FindFirstChild("Body")
or AP.aircraft:FindFirstChild("Fuselage")
or AP.aircraft:FindFirstChild("Main")
or hum.SeatPart
end
end
return
end
if not bvel or not bvel.Parent then
pcall(function()
bvel = Instance.new("BodyVelocity")
bvel.MaxForce = Vector3.new(1e9,1e9,1e9)
bvel.Velocity = Vector3.new(0,0,0)
bvel.P = 1e5
bvel.Parent = AP.rootPart
end); return
end
if not bgyro or not bgyro.Parent then
pcall(function()
bgyro = Instance.new("BodyGyro")
bgyro.MaxTorque = Vector3.new(1e9,1e9,1e9)
bgyro.P = 5e4; bgyro.D = 3000
bgyro.CFrame = AP.rootPart.CFrame
bgyro.Parent = AP.rootPart
end); return
end
local pos = AP.rootPart.Position
local alt = getAlt()
local arrThr = AP.arrRunway.threshold
local arrDir = headingDir(AP.arrRunway.heading)
local depDir = headingDir(AP.depRunway.heading)
if AP.phase == "TAKEOFF" then
spd = math.min(spd + math.max(AP.TAKEOFF_SPD*0.5,300)*dt, AP.TAKEOFF_SPD)
local pitchY = math.tan(math.rad(AP.CLIMB_PITCH))
local moveDir = (depDir + Vector3.new(0,pitchY,0)).Unit
fly(moveDir*spd, moveDir)
if alt >= AP.CRUISE_ALT then
AP.phase = "CRUISE"; spd = AP.CRUISE_SPD
task.spawn(function() pressKey("G") end)
end
elseif AP.phase == "CRUISE" then
if wpIndex > #waypoints then AP.phase="APPROACH"; spd=AP.LANDING_SPD; return end
local wp = waypoints[wpIndex]
local d2D = dist2D(pos, wp.pos)
local toTarget = Vector3.new(wp.pos.X-pos.X, 0, wp.pos.Z-pos.Z)
local hDir = d2D > 1 and toTarget.Unit or arrDir
local altErr = wp.pos.Y - alt
local yComp = math.clamp(altErr*0.003, -0.1, 0.1)
fly((hDir + Vector3.new(0,yComp,0)).Unit * AP.CRUISE_SPD, hDir)
if d2D < 800 then
wp.onArrive(); wpIndex = wpIndex + 1
end
elseif AP.phase == "APPROACH" then
spd = AP.LANDING_SPD
local toThr = Vector3.new(arrThr.X-pos.X, 0, arrThr.Z-pos.Z)
local hDir = toThr.Magnitude > 1 and toThr.Unit or arrDir
local heightAbove = alt - arrThr.Y
local dThresh = dist2D(pos, arrThr)
local sinkY = dThresh > 5 and -math.clamp(heightAbove/dThresh, 0, 0.5) or 0
if heightAbove < 80 then sinkY = math.max(sinkY,-0.08) end
if heightAbove < 30 then sinkY = math.max(sinkY,-0.04) end
if heightAbove < 10 then sinkY = math.max(sinkY,-0.01) end
if heightAbove < 3 then sinkY = 0 end
fly((hDir + Vector3.new(0,sinkY,0)).Unit * spd, hDir)
if heightAbove <= 3 or (dThresh < 15 and heightAbove < 15) then
AP.phase = "ROLLOUT"
task.spawn(function() pressKey("R") end)
end
elseif AP.phase == "ROLLOUT" then
local toThr = Vector3.new(arrThr.X-pos.X, 0, arrThr.Z-pos.Z)
local hDir = toThr.Magnitude > 10 and toThr.Unit or arrDir
spd = math.max(spd - math.max(AP.LANDING_SPD*0.5,200)*dt, 0)
fly(hDir*spd, hDir)
if spd <= 2 then
fly(Vector3.new(0,0,0), hDir)
task.spawn(function() pressKey("R"); task.wait(0.2); pressKey("X") end)
stopAP("Uçuş tamamlandı")
end
end
end)
end
local function startAP()
if AP.active then return false, "Zaten aktif!" end
if not AP.depRunway then return false, "Kalkış pisti seç!" end
if not AP.arrRunway then return false, "İniş pisti seç!" end
local char = Player.Character
if not char then return false, "Karakter yok!" end
local hum = char:FindFirstChildOfClass("Humanoid")
if not hum or not hum.SeatPart then return false, "Uçağa otur!" end
local ac = hum.SeatPart.Parent
local root = ac:FindFirstChild("Body") or ac:FindFirstChild("Fuselage")
or ac:FindFirstChild("Main") or hum.SeatPart
AP.aircraft = ac; AP.rootPart = root
AP.active = true; AP.phase = "TAKEOFF"
if bvel and bvel.Parent then bvel:Destroy() end
if bgyro and bgyro.Parent then bgyro:Destroy() end
bvel = Instance.new("BodyVelocity")
bvel.MaxForce = Vector3.new(1e9,1e9,1e9); bvel.Velocity = Vector3.new(0,0,0); bvel.P = 1e5
bvel.Parent = root
bgyro = Instance.new("BodyGyro")
bgyro.MaxTorque = Vector3.new(1e9,1e9,1e9); bgyro.P = 5e4; bgyro.D = 3000
bgyro.CFrame = root.CFrame; bgyro.Parent = root
local depDir = headingDir(AP.depRunway.heading)
local spawnPos = AP.depRunway.threshold - depDir * 80
spawnPos = Vector3.new(spawnPos.X, AP.depRunway.threshold.Y+3, spawnPos.Z)
local ok = pcall(function() ac:PivotTo(CFrame.new(spawnPos, spawnPos+depDir)) end)
if not ok then
local offset = spawnPos - root.Position
for _, p in pairs(ac:GetDescendants()) do
if p:IsA("BasePart") then p.CFrame = p.CFrame + offset end
end
end
buildWaypoints()
task.wait(0.5)
task.spawn(function() pressKey("E"); task.wait(0.3); pressKey("F") end)
task.wait(0.6)
startLoop()
return true, "Uçuş başladı! 🛫"
end
Player.CharacterAdded:Connect(function()
if AP.active then stopAP("Karakter sıfırlandı") end
end)
-- ════════════════════════════════════════════════════════
-- UI RENK PALETİ
-- ════════════════════════════════════════════════════════
local C = {
bg = Color3.fromRGB(8, 12, 18),
panel = Color3.fromRGB(12, 18, 28),
panelB = Color3.fromRGB(16, 24, 38),
border = Color3.fromRGB(35, 55, 80),
borderHi = Color3.fromRGB(60, 120, 200),
green = Color3.fromRGB(0, 230, 130),
greenD = Color3.fromRGB(0, 140, 70),
cyan = Color3.fromRGB(40, 200, 255),
cyanD = Color3.fromRGB(0, 100, 160),
amber = Color3.fromRGB(255, 190, 0),
amberD = Color3.fromRGB(140, 90, 0),
red = Color3.fromRGB(255, 65, 65),
redD = Color3.fromRGB(120, 20, 20),
white = Color3.fromRGB(220, 232, 245),
dim = Color3.fromRGB(90, 110, 135),
sky = Color3.fromRGB(30, 90, 180),
skyHi = Color3.fromRGB(60, 140, 255),
ground = Color3.fromRGB(110, 70, 30),
groundHi = Color3.fromRGB(160, 110, 50),
magenta = Color3.fromRGB(200, 60, 200),
}
-- ════════════════════════════════════════════════════════
-- UI BUILDER ARAÇLARI
-- ════════════════════════════════════════════════════════
local function F(parent, sx, sy, ox, oy, px, py, popx, popy, col, transp, zi)
local f = Instance.new("Frame")
f.Size = UDim2.new(sx or 0, ox or 0, sy or 0, oy or 0)
f.Position = UDim2.new(px or 0, popx or 0, py or 0, popy or 0)
-- col güvenlik: sadece Color3 kabul et
if typeof(col) == "Color3" then
f.BackgroundColor3 = col
else
f.BackgroundColor3 = C.panel
end
f.BackgroundTransparency = (typeof(transp) == "number") and transp or 0
f.BorderSizePixel = 0
f.ZIndex = (typeof(zi) == "number") and zi or 1
f.Parent = parent
return f
end
local function L(parent, text, ts, col, font, xa, sx, sy, ox, oy, px, py, popx, popy, zi)
local l = Instance.new("TextLabel")
l.Text = text or ""
l.TextSize = ts or 12
l.TextColor3 = col or C.white
l.Font = font or Enum.Font.Code
l.BackgroundTransparency = 1
l.TextXAlignment = xa or Enum.TextXAlignment.Center
l.Size = UDim2.new(sx or 1, ox or 0, sy or 1, oy or 0)
l.Position = UDim2.new(px or 0, popx or 0, py or 0, popy or 0)
l.ZIndex = zi or 2
l.Parent = parent
return l
end
local function Btn(parent, text, ts, col, bgcol, sx, sy, ox, oy, px, py, popx, popy, zi)
local b = Instance.new("TextButton")
b.Text = text or ""
b.TextSize = ts or 12
b.TextColor3 = col or C.white
b.Font = Enum.Font.GothamBold
b.BackgroundColor3 = bgcol or C.panel
b.BorderSizePixel = 0
b.AutoButtonColor = false
b.Size = UDim2.new(sx or 0, ox or 80, sy or 0, oy or 24)
b.Position = UDim2.new(px or 0, popx or 0, py or 0, popy or 0)
b.ZIndex = zi or 3
b.Parent = parent
return b
end
local function Rnd(inst, r)
local c = Instance.new("UICorner")
c.CornerRadius = UDim.new(0, r or 4)
c.Parent = inst
end
local function Str(inst, col, thick)
local s = Instance.new("UIStroke")
s.Color = col or C.border
s.Thickness = thick or 1
s.Parent = inst
end
local function makeDraggable(handle, target)
local drag, ds, sp = false, nil, nil
handle.InputBegan:Connect(function(i)
if i.UserInputType == Enum.UserInputType.MouseButton1 then
drag=true; ds=i.Position; sp=target.Position
end
end)
handle.InputEnded:Connect(function(i)
if i.UserInputType == Enum.UserInputType.MouseButton1 then drag=false end
end)
UIS.InputChanged:Connect(function(i)
if drag and i.UserInputType == Enum.UserInputType.MouseMovement then
local d = i.Position - ds
target.Position = UDim2.new(sp.X.Scale, sp.X.Offset+d.X, sp.Y.Scale, sp.Y.Offset+d.Y)
end
end)
end
-- ════════════════════════════════════════════════════════
-- ANA SCREENGUI
-- ════════════════════════════════════════════════════════
local sg = Instance.new("ScreenGui")
sg.Name = "PTFSMain"
sg.ResetOnSpawn = false
sg.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
sg.DisplayOrder = 100
sg.Parent = PlayerGui
-- ════════════════════════════════════════════════════════
-- ════ KOKPIT HUD ══════════════════════════════════════
-- ════════════════════════════════════════════════════════
-- Boyutlar
local HW, HH = 720, 260 -- HUD genişlik/yükseklik
local TH = 26 -- başlık bar
local SPD_W = 64 -- hız bant genişliği
local ALT_W = 72 -- irtifa bant
local PFD_W = HW - SPD_W - ALT_W - 4 -- 580
local PFD_H = HH - TH - 2
local ND_W = 140
local AI_W = PFD_W - ND_W - 2 -- yapay ufuk genişliği
-- HUD ana çerçeve
local hud = F(sg, 0, 0, HW, HH, 0.5, 1, -HW/2, -HH-8, C.bg, 0, 1)
Rnd(hud, 10)
Str(hud, C.borderHi, 1.5)
-- HUD başlık
local hudTitle = F(hud, 1, 0, 0, TH, 0, 0, 0, 0, Color3.fromRGB(10,16,28), 0, 2)
Rnd(hudTitle, 10)
L(hudTitle, "✈ PTFS FLIGHT DECK v15", 11, C.cyan, Enum.Font.GothamBold)
-- Üst sağ: kapat
local hudClose = Btn(hud, "✕", 11, C.white, C.redD, 0, 0, 22, 20, 1, 0, -26, 3, 5)
Rnd(hudClose, 4)
Str(hudClose, C.red, 1)
-- İçerik konteyneri
local hudC = F(hud, 1, 1, -2, -(TH+2), 0, 0, 1, TH+1, Color3.fromRGB(0,0,0), 1, 1)
-- makeDraggable(hudTitle, hud) -- başlıktan drag
-- ─── SPD BANT (sol) ─────────────────────────────────────
local spdPanel = F(hudC, 0, 1, SPD_W, 0, 0, 0, 0, 0, Color3.fromRGB(10,16,14), 0, 2)
Rnd(spdPanel, 6)
Str(spdPanel, Color3.fromRGB(0,80,50), 1)
L(spdPanel, "SPD", 8, C.greenD, Enum.Font.GothamBold, nil, 1, 0, 0, 14, 0, 0, 0, 0, 3)
L(spdPanel, "KTS", 8, C.greenD, Enum.Font.GothamBold, nil, 1, 0, 0, 14, 1, 0, 0, -14, 3)
-- Hız değer kutusu
local spdBox = F(spdPanel, 1, 0, -8, 30, 0, 0, 4, 0, Color3.fromRGB(0,20,12), 0, 3)
spdBox.Position = UDim2.new(0, 4, 0.5, -15)
Rnd(spdBox, 4)
Str(spdBox, C.green, 1)
local spdVal = L(spdBox, "0", 17, C.green, Enum.Font.Code, nil, 1, 1, 0, 0, 0, 0, 0, 0, 4)
-- Hız ticks
local spdTickContainer = F(spdPanel, 1, 1, 0, -34, 0, 0, 0, 16, Color3.fromRGB(0,0,0), 1, 2)
spdTickContainer.ClipsDescendants = true
for i = 0, 20 do
local v = i * 50
local yPct = 1 - (v / 1000)
local major = v % 100 == 0
local tick = F(spdTickContainer, 0, 0, major and 18 or 10, 1,
1, 0, -(major and 18 or 10), 0,
0, yPct, 0, -1,
major and Color3.fromRGB(0,180,80) or Color3.fromRGB(0,80,40), 0, 3)
if major then
L(spdTickContainer, tostring(v), 8, Color3.fromRGB(0,160,70), Enum.Font.Code,
Enum.TextXAlignment.Right,
0, 0, SPD_W-22, 14, 0, yPct, 0, -8, 3)
end
end
-- Hız pointer (sabit orta çizgi)
local spdPtr = F(spdPanel, 1, 0, -4, 2, 0, 0.5, 2, -1, C.green, 0, 5)
-- ─── ALT BANT (sağ) ─────────────────────────────────────
local altPanel = F(hudC, 0, 1, ALT_W, 0, 1, 0, -ALT_W, 0, Color3.fromRGB(10,12,22), 0, 2)
Rnd(altPanel, 6)
Str(altPanel, Color3.fromRGB(30,50,120), 1)
L(altPanel, "ALT", 8, C.cyanD, Enum.Font.GothamBold, nil, 1, 0, 0, 14, 0, 0, 0, 0, 3)
L(altPanel, "STD", 8, C.cyanD, Enum.Font.GothamBold, nil, 1, 0, 0, 14, 1, 0, 0, -14, 3)
local altBox = F(altPanel, 1, 0, -8, 30, 0, 0, 4, 0, Color3.fromRGB(5,8,28), 0, 3)
altBox.Position = UDim2.new(0, 4, 0.5, -15)
Rnd(altBox, 4)
Str(altBox, C.cyan, 1)
local altVal = L(altBox, "0", 15, C.cyan, Enum.Font.Code, nil, 1, 1, 0, 0, 0, 0, 0, 0, 4)
-- Alt ticks
local altTickContainer = F(altPanel, 1, 1, 0, -34, 0, 0, 0, 16, Color3.fromRGB(0,0,0), 1, 2)
altTickContainer.ClipsDescendants = true
for i = 0, 16 do
local v = i * 500
local yPct = 1 - (v / 8000)
local major = true
F(altTickContainer, 0, 0, 14, 1, 0, yPct, 0, -1, Color3.fromRGB(40,80,180), 0, 3)
L(altTickContainer, tostring(v), 8, Color3.fromRGB(40,100,200), Enum.Font.Code,
Enum.TextXAlignment.Left,
0, 0, ALT_W-20, 14, 0, yPct, 16, -8, 3)
end
local altPtr = F(altPanel, 1, 0, -4, 2, 0, 0.5, 2, -1, C.cyan, 0, 5)
-- ─── PFD ORTA ALAN ──────────────────────────────────────
local pfdArea = F(hudC, 0, 1, PFD_W, 0, 0, 0, SPD_W+2, 0, Color3.fromRGB(0,0,0), 1, 1)
-- YAPAY UFUK (AI)
local aiW = AI_W
local ai = F(pfdArea, 0, 1, aiW, 0, 0, 0, 0, 0, C.sky, 0, 2)
Rnd(ai, 6)
ai.ClipsDescendants = true
-- Gökyüzü gradyan effect
local skyTop = F(ai, 1, 0.6, 0, 0, 0, 0, 0, 0, Color3.fromRGB(20, 70, 160), 0, 2)
local skyBot = F(ai, 1, 0.5, 0, 0, 0, 0.5, 0, 0, Color3.fromRGB(50, 120, 220), 0, 2)
-- Zemin
local gndTop = F(ai, 1, 0.5, 0, 0, 0, 0.5, 0, 0, Color3.fromRGB(130, 85, 35), 0, 2)
local gndBot = F(ai, 1, 0.5, 0, 0, 0, 1, 0, 0, Color3.fromRGB(90, 55, 20), 0, 2)
gndBot.AnchorPoint = Vector2.new(0, 1)
-- Ufuk çizgisi (hareketli)
local horizLine = F(ai, 1, 0, 0, 2, 0, 0.5, 0, -1, C.amber, 0, 5)
-- Pitch tikleri
for _, deg in ipairs({-15,-10,-5,5,10,15}) do
local yBase = 0.5 - (deg * 0.018)
local w = math.abs(deg) >= 10 and 0.42 or 0.28
local pl = F(ai, w, 0, 0, 1, (1-w)/2, yBase, 0, 0, Color3.fromRGB(220,220,200), 0.3, 4)
L(ai, string.format("%+d",deg), 8, Color3.fromRGB(220,220,180), Enum.Font.Code,
Enum.TextXAlignment.Right,
0, 0, (1-w)/2*aiW - 4, 12,
0, yBase, 0, -6, 4)
L(ai, string.format("%+d",deg), 8, Color3.fromRGB(220,220,180), Enum.Font.Code,
Enum.TextXAlignment.Left,
0, 0, (1-w)/2*aiW - 4, 12,
(1+w)/2, yBase, 4, -6, 4)
end
-- Uçak sembolü (sabit merkez)
-- Sol kanat
local wL = F(ai, 0, 0, 44, 3, 0.5, 0.5, -52, -1, Color3.fromRGB(255,210,0), 0, 6)
-- Sağ kanat
local wR = F(ai, 0, 0, 44, 3, 0.5, 0.5, 8, -1, Color3.fromRGB(255,210,0), 0, 6)
-- Center dot
local wDot = F(ai, 0, 0, 8, 8, 0.5, 0.5, -4, -4, Color3.fromRGB(255,210,0), 0, 6)
Rnd(wDot, 4)
-- Tail
local wTail = F(ai, 0, 0, 3, 14, 0.5, 0.5, -1, -14, Color3.fromRGB(255,210,0), 0, 6)
-- Flight path vector (FPV) — küçük daire
local fpvFrame = F(ai, 0, 0, 18, 18, 0.5, 0.5, -9, -9, Color3.fromRGB(0,0,0), 1, 7)
local fpvCircle = F(fpvFrame, 1, 1, 0, 0, 0, 0, 0, 0, Color3.fromRGB(0,0,0), 1, 7)
Str(fpvCircle, C.green, 1.5)
Rnd(fpvCircle, 9)
-- FPV çizgiler
F(fpvFrame, 0, 0, 8, 1, 1, 0.5, 1, 0, Color3.fromRGB(0,230,120), 0, 8)
F(fpvFrame, 0, 0, 8, 1, 0, 0.5, -9, 0, Color3.fromRGB(0,230,120), 0, 8)
F(fpvFrame, 0, 0, 1, 8, 0.5, 0, 0, -9, Color3.fromRGB(0,230,120), 0, 8)
-- Heading bar (AI'nin altı)
local hdgStripH = 28
local hdgStrip = F(pfdArea, 0, 0, aiW, hdgStripH, 0, 1, 0, -hdgStripH, Color3.fromRGB(10,14,24), 0, 3)
Str(hdgStrip, C.border, 1)
Rnd(hdgStrip, 4)
-- HDG tick'ler (sabit, 10°ler)
for i = 0, 35 do
local deg = i * 10
local xPct = deg / 360
local major = deg % 30 == 0
F(hdgStrip, 0, 0, 1, major and 10 or 6,
xPct, 0, 0, 0,
major and Color3.fromRGB(60,110,180) or Color3.fromRGB(30,55,90), 0, 4)
if major then
local dirs = {[0]="N",[90]="E",[180]="S",[270]="W"}
local txt = dirs[deg] or tostring(deg)
L(hdgStrip, txt, 8, Color3.fromRGB(60,120,200), Enum.Font.Code,
nil, 0, 0, 20, 12, xPct, 0, -10, 10, 4)
end
end
-- HDG pointer (hareketli üçgen)
local hdgPtr = F(hdgStrip, 0, 0, 2, 16, 0.5, 0, -1, 0, C.cyan, 0, 5)
-- HDG readout
local hdgReadBox = F(hdgStrip, 0, 1, 54, -4, 0.5, 0, -27, 2, Color3.fromRGB(5,10,30), 0, 5)
Rnd(hdgReadBox, 3)
Str(hdgReadBox, C.cyan, 1)
local hdgRead = L(hdgReadBox, "000°", 13, C.cyan, Enum.Font.Code, nil, 1, 1, 0, 0, 0, 0, 0, 0, 6)
-- Pitch/VS şeridi (AI üstü)
local topStrip = F(pfdArea, 0, 0, aiW, 22, 0, 0, 0, 0, Color3.fromRGB(8,12,20), 0, 3)
Rnd(topStrip, 4)
local pitchRead = L(topStrip, "PTH +0.0°", 10, C.amber, Enum.Font.Code,
Enum.TextXAlignment.Left, 0, 1, 0, 0, 0, 0, 6, 0, 4)
local vsRead = L(topStrip, "V/S +0", 10, C.green, Enum.Font.Code,
Enum.TextXAlignment.Right, 0, 1, 0, 0, 0, 0, -6, 0, 4)
-- ─── ND (NAV DISPLAY) sağ yarı ──────────────────────────
local ndX = aiW + 2
local nd = F(pfdArea, 0, 1, ND_W, 0, 0, 0, ndX, 0, Color3.fromRGB(8,10,20), 0, 2)
Rnd(nd, 6)
Str(nd, C.border, 1)
L(nd, "NAV", 9, C.cyan, Enum.Font.GothamBold, nil, 1, 0, 0, 18, 0, 0, 0, 0, 3)
-- Compass rose
local compassR = 52
local compassCX = ND_W / 2
local compassCY = 32 + compassR + 4
local compassBG = F(nd, 0, 0, compassR*2, compassR*2, 0.5, 0, -compassR, 22, Color3.fromRGB(8,12,24), 0, 3)
Rnd(compassBG, compassR)
Str(compassBG, Color3.fromRGB(40,65,100), 1)
-- Compass glow ring
local compassGlow = F(nd, 0, 0, compassR*2+6, compassR*2+6, 0.5, 0, -compassR-3, 19, Color3.fromRGB(0,0,0), 1, 2)
Rnd(compassGlow, compassR+3)
Str(compassGlow, Color3.fromRGB(20,50,100), 1)
-- Cardinal directions
local cardinals = {
{t="N", a=0, c=C.cyan},
{t="E", a=90, c=C.white},
{t="S", a=180, c=C.white},
{t="W", a=270, c=C.white},
}
for _, cd in ipairs(cardinals) do
local r2 = math.rad(cd.a)
local cx = math.sin(r2) * (compassR-10)
local cy = -math.cos(r2) * (compassR-10)
L(compassBG, cd.t, 9, cd.c, Enum.Font.GothamBold,
nil, 0, 0, 16, 14,
0.5, 0.5, cx-8, cy-7, 4)
end
-- Compass küçük tikleri (36 tane)
for i = 0, 35 do
local deg2 = i * 10
local r2 = math.rad(deg2)
local major2 = deg2 % 30 == 0
local r_in = compassR - (major2 and 10 or 6)
local r_out = compassR - 2
-- Tick as thin frame — approximate
local tx = math.sin(r2) * (r_in + (r_out-r_in)/2)
local ty = -math.cos(r2) * (r_in + (r_out-r_in)/2)
local tickDot = F(compassBG, 0, 0, major2 and 2 or 1, major2 and 2 or 1,
0.5, 0.5, tx-1, ty-1,
major2 and Color3.fromRGB(60,120,200) or Color3.fromRGB(30,60,100), 0, 4)
end
-- Uçak ikonu ortada
local planeIcon = L(compassBG, "✈", 16, C.white, Enum.Font.GothamBold,
nil, 0, 0, 22, 22, 0.5, 0.5, -11, -12, 5)
-- Compass needle (heading göstergesi)
local needleFrame = F(compassBG, 1, 1, 0, 0, 0, 0, 0, 0, Color3.fromRGB(0,0,0), 1, 5)
local needle = F(needleFrame, 0, 0, 2, compassR-8, 0.5, 0.5, -1, -(compassR-8), C.cyan, 0, 5)
-- HDG sayısal alt
local ndHdgLbl = L(nd, "000°", 14, C.cyan, Enum.Font.Code,
nil, 1, 0, 0, 20, 0, 0, 0, compassR*2+26, 3)
-- DEST / WP
local ndDestLbl = L(nd, "DEST: ---", 9, C.green, Enum.Font.Code,
nil, 1, 0, 0, 16, 0, 0, 0, compassR*2+48, 3)
local ndWPLbl = L(nd, "WP: -/-", 9, C.amber, Enum.Font.Code,
nil, 1, 0, 0, 16, 0, 0, 0, compassR*2+66, 3)
local ndPhaseLbl = L(nd, "IDLE", 10, C.red, Enum.Font.GothamBold,
nil, 1, 0, 0, 18, 0, 0, 0, compassR*2+84, 3)
-- ─── ALT BAR (HUD'un en altı) ───────────────────────────
local barH = 32
local bar = F(hud, 1, 0, 0, barH, 0, 1, 0, -barH-1, Color3.fromRGB(8,11,20), 0, 3)
Rnd(bar, 6)
Str(bar, C.border, 1)
local barCells = {
{k="gs", l="G/S", c=C.green},
{k="vs", l="V/S", c=C.cyan},
{k="dist", l="DIST", c=C.amber},
{k="wp", l="WYPT", c=Color3.fromRGB(180,180,255)},
{k="phase", l="PHASE", c=C.magenta},
{k="dep", l="DEP", c=C.dim},
{k="arr", l="ARR", c=C.dim},
}
local barVals = {}
local cw = HW / #barCells
for i, cell in ipairs(barCells) do
local cx = (i-1)*cw
local bg = F(bar, 0, 1, cw-2, -4, 0, 0, cx+1, 2, Color3.fromRGB(11,16,28), 0, 3)
Rnd(bg, 3)
L(bg, cell.l, 7, C.dim, Enum.Font.GothamBold, nil, 1, 0, 0, 12, 0, 0, 0, 2, 4)
barVals[cell.k] = L(bg, "--", 12, cell.c, Enum.Font.Code,
nil, 1, 0, 0, 16, 0, 0, 0, 12, 4)
if i < #barCells then
F(bar, 0, 1, 1, -8, 0, 0, cx+cw, 4, C.border, 0, 4)
end
end
-- HUD kapatma
hudClose.MouseButton1Click:Connect(function() hud.Visible = false end)
makeDraggable(hudTitle, hud)
-- ════════════════════════════════════════════════════════
-- ════ ANA MENÜ (Sidebar Sol) ════════════════════════════
-- ════════════════════════════════════════════════════════
local MENU_W = 220
local menuVisible = false
local menuPanel = F(sg, 0, 0, MENU_W, 480, 0, 0.5, 0, -240, C.bg, 0, 10)
menuPanel.Visible = false
Rnd(menuPanel, 10)
Str(menuPanel, C.borderHi, 1.5)
-- Menü başlık
local menuTitle = F(menuPanel, 1, 0, 0, 32, 0, 0, 0, 0, Color3.fromRGB(10,18,32), 0, 11)
Rnd(menuTitle, 10)
L(menuTitle, "✈ PTFS AP v15", 12, C.cyan, Enum.Font.GothamBold, nil, 1, 1, 0, 0, 0, 0, 0, 0, 12)
makeDraggable(menuTitle, menuPanel)
-- Menü kapat
local menuClose = Btn(menuPanel, "✕", 11, C.white, C.redD, 0, 0, 22, 22, 1, 0, -26, 5, 13)
Rnd(menuClose, 4)
-- Sekme sistemi
local tabs = {"Kalkış","İniş","Ayarlar","Kayıt"}
local tabBtns = {}
local tabContents = {}
local activeTab = 1
local tabBar = F(menuPanel, 1, 0, 0, 28, 0, 0, 0, 34, Color3.fromRGB(8,12,20), 0, 11)
local tabContentArea = F(menuPanel, 1, 1, 0, -64, 0, 0, 0, 64, Color3.fromRGB(0,0,0), 1, 11)
for i, name in ipairs(tabs) do
local tw = MENU_W / #tabs
local tbtn = Btn(tabBar, name, 9, C.dim, Color3.fromRGB(10,14,22),
0, 1, tw-2, 0, 0, 0, (i-1)*tw+1, 0, 12)
Rnd(tbtn, 3)
table.insert(tabBtns, tbtn)
-- içerik
local tc = F(tabContentArea, 1, 1, 0, 0, 0, 0, 0, 0, Color3.fromRGB(0,0,0), 1, 11)
tc.Visible = (i == 1)
table.insert(tabContents, tc)
tbtn.MouseButton1Click:Connect(function()
for j, tb in ipairs(tabBtns) do
tb.BackgroundColor3 = (j==i) and Color3.fromRGB(16,28,50) or Color3.fromRGB(10,14,22)
tb.TextColor3 = (j==i) and C.cyan or C.dim
tabContents[j].Visible = (j==i)
end
activeTab = i
end)
end
-- İlk sekme aktif rengi
tabBtns[1].BackgroundColor3 = Color3.fromRGB(16,28,50)
tabBtns[1].TextColor3 = C.cyan
-- ──── Scroll yardımcısı ─────────────────────────────────
local function makeScroll(parent, yOff)
local sf = Instance.new("ScrollingFrame")
sf.Size = UDim2.new(1, -4, 1, -(yOff or 0))
sf.Position = UDim2.new(0, 2, 0, yOff or 0)
sf.BackgroundTransparency = 1
sf.BorderSizePixel = 0
sf.ScrollBarThickness = 3
sf.ScrollBarImageColor3 = C.cyanD
sf.CanvasSize = UDim2.new(0,0,0,0)
sf.AutomaticCanvasSize = Enum.AutomaticSize.Y
sf.Parent = parent
local layout = Instance.new("UIListLayout")
layout.SortOrder = Enum.SortOrder.LayoutOrder
layout.Padding = UDim.new(0, 3)
layout.Parent = sf
return sf
end
-- ──── Seçili pist label'ı ───────────────────────────────
local function makeLabel(parent, initText, col)
local f = F(parent, 1, 0, -8, 24, 0, 0, 4, 0, Color3.fromRGB(10,16,28), 0, 12)
Rnd(f, 4)
Str(f, C.border, 1)
local l = L(f, initText, 10, col or C.dim, Enum.Font.Code, Enum.TextXAlignment.Left,
1, 1, -8, 0, 0, 0, 4, 0, 13)
-- layout için
f.Parent = parent
return l, f
end
-- ──── Seçim butonu fabrikası ────────────────────────────
local function runwayBtn(parent, apName, rwy, isArr)
local btnF = F(parent, 1, 0, -8, 28, 0, 0, 4, 0, Color3.fromRGB(12,18,32), 0, 12)
Rnd(btnF, 5)
Str(btnF, C.border, 1)
local lbl = string.format("RWY %s (%.1f°)", rwy.name, rwy.heading)
local lb = L(btnF, lbl, 10, C.white, Enum.Font.Code, Enum.TextXAlignment.Left,
1, 1, -8, 0, 0, 0, 6, 0, 13)
local clickBtn = Btn(btnF, "", 10, C.white, Color3.fromRGB(0,0,0),
1, 1, 0, 0, 0, 0, 0, 0, 14)
clickBtn.BackgroundTransparency = 1
clickBtn.MouseButton1Click:Connect(function()
if isArr then
AP.arrRunway = rwy
else
AP.depRunway = rwy
end
-- Flash efekti
local origCol = btnF.BackgroundColor3
TweenS:Create(btnF, TweenInfo.new(0.15), {BackgroundColor3 = isArr and C.cyanD or C.greenD}):Play()
task.delay(0.3, function()
TweenS:Create(btnF, TweenInfo.new(0.2), {BackgroundColor3 = origCol}):Play()
end)
end)
return btnF
end
-- ──── KALKIŞ SEKMESI ────────────────────────────────────
local depScroll = makeScroll(tabContents[1])
local depSelLabel
do
-- Seçili label
local hdr = F(depScroll, 1, 0, 0, 28, 0, 0, 0, 0, Color3.fromRGB(8,14,24), 0, 12)
Rnd(hdr, 4)
L(hdr, "KALKIŞ PİSTİ", 9, C.dim, Enum.Font.GothamBold)
local _, f2 = makeLabel(depScroll, "Seçilmedi", C.amber)
depSelLabel = L(f2, "Seçilmedi", 10, C.amber, Enum.Font.Code, Enum.TextXAlignment.Left,
1, 1, -8, 0, 0, 0, 4, 0, 14)
for _, ap in ipairs(Airports) do
local secHdr = F(depScroll, 1, 0, 0, 20, 0, 0, 0, 0, Color3.fromRGB(10,22,40), 0, 12)
Rnd(secHdr, 3)
L(secHdr, "📍 " .. ap.name, 9, C.cyan, Enum.Font.GothamBold, Enum.TextXAlignment.Left,
1, 1, -8, 0, 0, 0, 4, 0, 13)
for _, rwy in ipairs(ap.runways) do
local bf = runwayBtn(depScroll, ap.name, rwy, false)
-- Seçilince label güncelle
bf:FindFirstChildOfClass("TextButton").MouseButton1Click:Connect(function()
depSelLabel.Text = "✅ " .. ap.name .. " · RWY " .. rwy.name
depSelLabel.TextColor3 = C.green
end)
end
end
end
-- ──── İNİŞ SEKMESI ──────────────────────────────────────
local arrScroll = makeScroll(tabContents[2])
local arrSelLabel
do
local hdr = F(arrScroll, 1, 0, 0, 28, 0, 0, 0, 0, Color3.fromRGB(8,14,24), 0, 12)
Rnd(hdr, 4)
L(hdr, "İNİŞ PİSTİ", 9, C.dim, Enum.Font.GothamBold)
local _, f2 = makeLabel(arrScroll, "Seçilmedi", C.amber)
arrSelLabel = L(f2, "Seçilmedi", 10, C.amber, Enum.Font.Code, Enum.TextXAlignment.Left,
1, 1, -8, 0, 0, 0, 4, 0, 14)
for _, ap in ipairs(Airports) do
local secHdr = F(arrScroll, 1, 0, 0, 20, 0, 0, 0, 0, Color3.fromRGB(10,22,40), 0, 12)
Rnd(secHdr, 3)
L(secHdr, "📍 " .. ap.name, 9, C.cyan, Enum.Font.GothamBold, Enum.TextXAlignment.Left,
1, 1, -8, 0, 0, 0, 4, 0, 13)
for _, rwy in ipairs(ap.runways) do
local bf = runwayBtn(arrScroll, ap.name, rwy, true)
bf:FindFirstChildOfClass("TextButton").MouseButton1Click:Connect(function()
arrSelLabel.Text = "✅ " .. ap.name .. " · RWY " .. rwy.name
arrSelLabel.TextColor3 = C.cyan
end)
end
end
end
-- ──── AYARLAR SEKMESI ───────────────────────────────────
do
local scroll = makeScroll(tabContents[3])
local function makeSlider(parent, label, min, max, default, suffix, callback)
local grp = F(parent, 1, 0, 0, 56, 0, 0, 0, 0, Color3.fromRGB(10,16,28), 0, 12)
Rnd(grp, 5)
Str(grp, C.border, 1)
L(grp, label, 9, C.dim, Enum.Font.GothamBold, Enum.TextXAlignment.Left,
1, 0, -8, 14, 0, 0, 4, 4, 13)
local valLbl = L(grp, tostring(default)..suffix, 10, C.cyan, Enum.Font.Code,
Enum.TextXAlignment.Right, 0, 0, 60, 14, 1, 0, -64, 4, 13)
-- Slider track
local track = F(grp, 1, 0, -16, 6, 0, 0, 8, 34, Color3.fromRGB(20,30,50), 0, 13)
Rnd(track, 3)
local fill = F(track, 0, 1, 0, 0, 0, 0, 0, 0, C.cyanD, 0, 14)
Rnd(fill, 3)
local thumb = F(track, 0, 0, 10, 10, 0, 0.5, -5, -5, C.cyan, 0, 15)
Rnd(thumb, 5)
local function setVal(v)
v = math.clamp(math.floor(v), min, max)
local pct = (v-min)/(max-min)
fill.Size = UDim2.new(pct, 0, 1, 0)
thumb.Position = UDim2.new(pct, -5, 0.5, -5)
valLbl.Text = tostring(v)..suffix
if callback then callback(v) end
end
setVal(default)
-- Drag slider
local draggingSlider = false
thumb.InputBegan:Connect(function(i)
if i.UserInputType == Enum.UserInputType.MouseButton1 then
draggingSlider = true
end
end)
UIS.InputEnded:Connect(function(i)
if i.UserInputType == Enum.UserInputType.MouseButton1 then
draggingSlider = false
end
end)
UIS.InputChanged:Connect(function(i)
if draggingSlider and i.UserInputType == Enum.UserInputType.MouseMovement then
local rect = track.AbsolutePosition
local w = track.AbsoluteSize.X
local pct = math.clamp((i.Position.X - rect.X) / w, 0, 1)
setVal(min + pct*(max-min))
end
end)
track.InputBegan:Connect(function(i)
if i.UserInputType == Enum.UserInputType.MouseButton1 then
local w = track.AbsoluteSize.X
local pct = math.clamp((i.Position.X - track.AbsolutePosition.X) / w, 0, 1)
setVal(min + pct*(max-min))
end
end)
return grp
end
makeSlider(scroll, "Kalkış Hızı", 100, 20000, 280, " kts", function(v) AP.TAKEOFF_SPD=v end)
makeSlider(scroll, "Cruise Hızı", 150, 20000, 350, " kts", function(v) AP.CRUISE_SPD=v end)
makeSlider(scroll, "İniş Hızı", 60, 20000, 110, " kts", function(v) AP.LANDING_SPD=v end)
makeSlider(scroll, "Cruise İrtifa", 500, 8000, 2000, " stud", function(v) AP.CRUISE_ALT=v end)
makeSlider(scroll, "Kalkış Açısı", 5, 25, 15, "°", function(v) AP.CLIMB_PITCH=v end)
end
-- ──── KAYIT SEKMESI ─────────────────────────────────────
do
local scroll = makeScroll(tabContents[4])
local function makeInput(parent, placeholder, callback)
local box = Instance.new("TextBox")
box.Size = UDim2.new(1, -8, 0, 26)
box.Position = UDim2.new(0, 4, 0, 0)
box.PlaceholderText = placeholder
box.Text = ""
box.TextSize = 10
box.Font = Enum.Font.Code
box.TextColor3 = C.white
box.PlaceholderColor3 = C.dim
box.BackgroundColor3 = Color3.fromRGB(10,16,28)
box.BorderSizePixel = 0
box.ClearTextOnFocus = false
box.ZIndex = 13
box.Parent = parent
Rnd(box, 4)
Str(box, C.border, 1)
box.FocusLost:Connect(function() if callback then callback(box.Text) end end)
return box
end
local recApName, recRwyName = "Yeni Havalimanı", "00"
local livePosLbl, lastSaveLbl
local hdr1 = F(scroll, 1, 0, 0, 20, 0, 0, 0, 0, Color3.fromRGB(8,14,24), 0, 12)
Rnd(hdr1, 3)
L(hdr1, "PİST KAYDET", 9, C.dim, Enum.Font.GothamBold)
makeInput(scroll, "Havalimanı adı", function(t) if t~="" then recApName=t end end)
makeInput(scroll, "Pist numarası (örn: 07R)", function(t) if t~="" then recRwyName=t end end)
local posF = F(scroll, 1, 0, 0, 24, 0, 0, 0, 0, Color3.fromRGB(8,12,20), 0, 12)
Rnd(posF, 3)
livePosLbl = L(posF, "Konum: -", 9, C.dim, Enum.Font.Code, Enum.TextXAlignment.Left,
1, 1, -8, 0, 0, 0, 4, 0, 13)
local saveBtn = Btn(scroll, "💾 KAYDET", 11, C.green, Color3.fromRGB(0,25,12),
1, 0, -8, 28, 0, 0, 4, 0, 13)
Rnd(saveBtn, 5)
Str(saveBtn, C.green, 1)
local lastF = F(scroll, 1, 0, 0, 32, 0, 0, 0, 0, Color3.fromRGB(8,12,20), 0, 12)
Rnd(lastF, 3)
lastSaveLbl = L(lastF, "Son kayıt: -", 9, C.dim, Enum.Font.Code, Enum.TextXAlignment.Left,
1, 1, -8, 0, 0, 0, 4, 0, 13)
saveBtn.MouseButton1Click:Connect(function()
pcall(function()
local char = Player.Character
if not char then return end
local hrp = char:FindFirstChild("HumanoidRootPart")
if not hrp then return end
local cam = game:GetService("Workspace").CurrentCamera
local flat = Vector3.new(cam.CFrame.LookVector.X, 0, cam.CFrame.LookVector.Z).Unit
local hdg = math.deg(math.atan2(flat.X, flat.Z))
if hdg < 0 then hdg = hdg + 360 end
local pos = hrp.Position
local thr = Vector3.new(math.floor(pos.X*10)/10, math.floor(pos.Y*10)/10, math.floor(pos.Z*10)/10)
local newRwy = { name=recRwyName, threshold=thr, heading=math.floor(hdg*10)/10 }
local oppHdg = (hdg+180)%360
local rwyNum = tonumber(recRwyName:match("%d+"))
local oppNum = rwyNum and ((rwyNum+17)%36+1) or nil
local oppName = oppNum and string.format("%02d",oppNum) or (recRwyName.."_R")
local oppRwy = { name=oppName, threshold=thr, heading=math.floor(oppHdg*10)/10 }
local apFound
for _, ap in ipairs(Airports) do
if ap.name==recApName then apFound=ap; break end
end
if not apFound then
apFound = { name=recApName, runways={} }
table.insert(Airports, apFound)
end
table.insert(apFound.runways, newRwy)
table.insert(apFound.runways, oppRwy)
-- Kalkış/iniş sekmelerine ekle
for _, isArr in ipairs({false, true}) do
local scr = isArr and arrScroll or depScroll
local secHdr = F(scr, 1, 0, 0, 20, 0, 0, 0, 0, Color3.fromRGB(10,22,40), 0, 12)
Rnd(secHdr, 3)
L(secHdr, "📍 "..recApName, 9, C.cyan, Enum.Font.GothamBold, Enum.TextXAlignment.Left,
1, 1, -8, 0, 0, 0, 4, 0, 13)
for _, rwy2 in ipairs({newRwy, oppRwy}) do
runwayBtn(scr, recApName, rwy2, isArr)
end
end
lastSaveLbl.Text = string.format("✅ %s RWY%s + RWY%s (%.0f°/%.0f°)",
recApName, recRwyName, oppName, hdg, oppHdg)
lastSaveLbl.TextColor3 = C.green
end)
end)
-- Canlı konum
task.spawn(function()
while task.wait(0.3) do
pcall(function()
local char = Player.Character
if not char then return end
local hrp = char:FindFirstChild("HumanoidRootPart")
if not hrp then return end
local cam = game:GetService("Workspace").CurrentCamera
local flat = Vector3.new(cam.CFrame.LookVector.X, 0, cam.CFrame.LookVector.Z).Unit
local hdg = math.deg(math.atan2(flat.X, flat.Z))
if hdg < 0 then hdg = hdg + 360 end
local p = hrp.Position
livePosLbl.Text = string.format("X:%d Y:%d Z:%d %03.0f°", p.X, p.Y, p.Z, hdg)
end)
end
end)
end
-- ════════════════════════════════════════════════════════
-- ════ AP KONTROL MENÜSÜ (popup, AP butonuna basınca) ════
-- ════════════════════════════════════════════════════════
local AP_W, AP_H = 240, 200
local apMenu = F(sg, 0, 0, AP_W, AP_H, 0, 0.5, 0, -AP_H/2, C.bg, 0, 20)
apMenu.Visible = false
Rnd(apMenu, 10)
Str(apMenu, C.borderHi, 1.5)
local apMenuTitle = F(apMenu, 1, 0, 0, 30, 0, 0, 0, 0, Color3.fromRGB(10,20,40), 0, 21)
Rnd(apMenuTitle, 10)
L(apMenuTitle, "AUTOPILOT KONTROL", 11, C.cyan, Enum.Font.GothamBold)
makeDraggable(apMenuTitle, apMenu)
local apMenuClose = Btn(apMenu, "✕", 11, C.white, C.redD, 0, 0, 22, 22, 1, 0, -26, 4, 22)
Rnd(apMenuClose, 4)
apMenuClose.MouseButton1Click:Connect(function() apMenu.Visible = false end)
-- AP Durum
local apStatF = F(apMenu, 1, 0, -12, 28, 0, 0, 6, 34, Color3.fromRGB(10,30,10), 0, 21)
Rnd(apStatF, 5)
Str(apStatF, C.greenD, 1)
local apStatLbl = L(apStatF, "● AP OFF", 13, C.red, Enum.Font.GothamBold, nil, 1, 1, 0, 0, 0, 0, 0, 0, 22)
-- Rota özeti
local routeF = F(apMenu, 1, 0, -12, 24, 0, 0, 6, 66, Color3.fromRGB(8,12,24), 0, 21)
Rnd(routeF, 4)
local routeLbl = L(routeF, "DEP: -- → ARR: --", 9, C.dim, Enum.Font.Code,
Enum.TextXAlignment.Left, 1, 1, -8, 0, 0, 0, 4, 0, 22)
-- WP bilgi
local wpF = F(apMenu, 1, 0, -12, 20, 0, 0, 6, 94, Color3.fromRGB(8,10,20), 0, 21)
Rnd(wpF, 3)
local wpLbl = L(wpF, "PHASE: IDLE WP: -/-", 9, C.amber, Enum.Font.Code,
Enum.TextXAlignment.Left, 1, 1, -8, 0, 0, 0, 4, 0, 22)
-- BAŞLAT butonu
local startBtn = Btn(apMenu, "▶ AUTOPILOT BAŞLAT", 12, C.green, Color3.fromRGB(0,30,15),
1, 0, -12, 30, 0, 0, 6, 120, 22)
Rnd(startBtn, 6)
Str(startBtn, C.green, 1)
startBtn.MouseButton1Click:Connect(function()
local ok, msg = startAP()
startBtn.Text = ok and "✅ " .. msg or "❌ " .. msg
task.delay(2, function() startBtn.Text = "▶ AUTOPILOT BAŞLAT" end)
end)
-- DURDUR butonu
local stopBtn = Btn(apMenu, "■ DURDUR", 12, C.red, Color3.fromRGB(30,8,8),
1, 0, -12, 28, 0, 0, 6, 156, 22)
Rnd(stopBtn, 6)
Str(stopBtn, C.red, 1)
stopBtn.MouseButton1Click:Connect(function()
stopAP("Manuel")
end)
-- AP menü durum güncelle
task.spawn(function()
while task.wait(0.3) do
pcall(function()
if AP.active then
apStatLbl.Text = "● AP ON — " .. AP.phase
apStatLbl.TextColor3 = C.green
apStatF.BackgroundColor3 = Color3.fromRGB(5,30,12)
else
apStatLbl.Text = "● AP OFF"
apStatLbl.TextColor3 = C.red
apStatF.BackgroundColor3 = Color3.fromRGB(25,8,8)
end
local dep = AP.depRunway and AP.depRunway.name or "--"
local arr = AP.arrRunway and AP.arrRunway.name or "--"
routeLbl.Text = "DEP: " .. dep .. " → ARR: " .. arr
wpLbl.Text = string.format("PHASE: %s WP: %s/%s",
AP.phase, tostring(wpIndex), tostring(#waypoints))
end)
end
end)
-- ════════════════════════════════════════════════════════
-- ════ SAĞ DOCK (Buton Grubu) ════════════════════════════
-- ════════════════════════════════════════════════════════
local dockW = 116
local dock = F(sg, 0, 0, dockW, 130, 1, 0.5, -dockW-8, -65, Color3.fromRGB(8,12,20), 0, 15)
Rnd(dock, 8)
Str(dock, C.border, 1)
-- Logo/başlık
local dockTitle = F(dock, 1, 0, 0, 22, 0, 0, 0, 0, Color3.fromRGB(10,16,30), 0, 16)
Rnd(dockTitle, 8)
L(dockTitle, "✈ PTFS v15", 9, C.cyan, Enum.Font.GothamBold)
local function dockBtn(y, txt, bg, brd, callback)
local b = Btn(dock, txt, 10, C.white, bg,
1, 0, -8, 26, 0, 0, 4, y, 16)
Rnd(b, 5)
Str(b, brd, 1)
b.MouseButton1Click:Connect(callback)
return b
end
-- Menü butonu
dockBtn(26, "☰ MENÜ", Color3.fromRGB(12,20,40), C.borderHi, function()
menuVisible = not menuVisible
menuPanel.Visible = menuVisible
-- Menüyü dock'un soluna konumlandır
if menuVisible then
menuPanel.Position = UDim2.new(1, -dockW-8-MENU_W-8, 0.5, -240)
end
end)
-- AP butonu
local apDockBtn = dockBtn(56, "✈ AUTOPILOT", Color3.fromRGB(0,18,8), C.green, function()
apMenu.Visible = not apMenu.Visible
if apMenu.Visible then
-- Dock'un solunda görünsün
apMenu.Position = UDim2.new(1, -dockW-8-AP_W-8, 0.5, -AP_H/2)
end
end)
Str(apDockBtn, C.green, 1)
-- HUD butonu
dockBtn(86, "🖥 KOKPİT", Color3.fromRGB(8,12,28), C.borderHi, function()
hud.Visible = not hud.Visible
end)
-- AP durum indikatör (dock)
local dockAPF = F(dock, 1, 0, -8, 12, 0, 0, 4, 116, Color3.fromRGB(25,8,8), 0, 16)
Rnd(dockAPF, 3)
local dockAPLbl = L(dockAPF, "AP OFF", 8, C.red, Enum.Font.GothamBold, nil, 1, 1, 0, 0, 0, 0, 0, 0, 17)
task.spawn(function()
while task.wait(0.5) do pcall(function()
dockAPLbl.Text = AP.active and ("AP "..AP.phase) or "AP OFF"
dockAPLbl.TextColor3 = AP.active and C.green or C.red
dockAPF.BackgroundColor3 = AP.active and Color3.fromRGB(5,30,10) or Color3.fromRGB(25,8,8)
-- AP butonu rengi
apDockBtn.BackgroundColor3 = AP.active and Color3.fromRGB(0,30,12) or Color3.fromRGB(0,18,8)
end) end
end)
-- ════════════════════════════════════════════════════════
-- ════ HUD CANLI GÜNCELLEME ══════════════════════════════
-- ════════════════════════════════════════════════════════
local prevAlt = 0
RunService.Heartbeat:Connect(function()
if not hud.Visible then return end
pcall(function()
local char = Player.Character
if not char then return end
local hrp = char:FindFirstChild("HumanoidRootPart")
if not hrp then return end
local vel = hrp.AssemblyLinearVelocity
local gs = math.floor(vel.Magnitude)
local alt = math.floor(hrp.Position.Y)
local look = hrp.CFrame.LookVector
-- Heading
local hdg = math.deg(math.atan2(look.X, look.Z))
if hdg < 0 then hdg = hdg + 360 end
-- Pitch
local pitch = 0
if vel.Magnitude > 0.5 then
pitch = math.deg(math.asin(math.clamp(vel.Y/vel.Magnitude, -1, 1)))
end
-- VS
local vs = math.floor(vel.Y * 60)
-- ─ SPD TAPE ─
spdVal.Text = tostring(gs)
-- Hız bandı kaydırma: büyük sayı = yukarı kayması lazım
-- 1 stud = 20px, band 1000'e kadar
do
local spdPanelH = spdTickContainer.AbsoluteSize.Y
local totalH = 1000 -- 0-1000 aralığı
local pxPerUnit = spdPanelH / totalH * 1000
-- gs'ye karşılık gelen yüzde (0-1)
-- 0 = en alt, 1000 = en üst
-- Orta göstermek için: pointer ortada sabit, ticks yukarı/aşağı kayıyor
-- Yüksek hız → ticks yukarı kaymış
local offset = math.clamp((gs/1000) * spdPanelH, 0, spdPanelH)
-- Tick container'ı kaydır (negative Y = aşağı doğru görünür)
-- Ticks sabit ama şu an absolute position ile kayma yok
-- Renk güncelle: hız rengi
local speedColor
if gs < 100 then speedColor = C.red
elseif gs < 200 then speedColor = C.amber
else speedColor = C.green end
spdVal.TextColor3 = speedColor
end
-- ─ ALT TAPE ─
altVal.Text = tostring(alt)
do
local altColor
if alt < 50 then altColor = C.amber
elseif alt < 200 then altColor = C.white
else altColor = C.cyan end
altVal.TextColor3 = altColor
end
-- ─ YAPAY UFUK ─
-- Pitch: +pitch = ufuk aşağıya iner (gökyüzü büyür)
-- Her derece = PFD_H*0.018 piksel
local aiH = ai.AbsoluteSize.Y
local pxPitch = math.clamp(pitch * (aiH * 0.018), -(aiH*0.45), aiH*0.45)
local skyRatio = math.clamp(0.5 + pxPitch/aiH, 0.05, 0.95)
skyTop.Size = UDim2.new(1, 0, skyRatio, 0)
skyBot.Size = UDim2.new(1, 0, skyRatio, 0)
gndTop.Position = UDim2.new(0, 0, skyRatio, 0)
gndTop.Size = UDim2.new(1, 0, 1-skyRatio, 0)
gndBot.Position = UDim2.new(0, 0, 1, 0)
gndBot.Size = UDim2.new(1, 0, 1-skyRatio, 0)
horizLine.Position = UDim2.new(0, 0, skyRatio, -1)
-- FPV (flight path vector) - hız yönüne göre
if vel.Magnitude > 2 then
local fpvPitch = math.deg(math.asin(math.clamp(vel.Y/vel.Magnitude,-1,1)))
local fpvYawOff = 0 -- yaw offset basit
local fpvYPx = -fpvPitch * (aiH * 0.018)
fpvFrame.Position = UDim2.new(0.5, -9, 0.5, fpvYPx - 9)
fpvFrame.Visible = true
else
fpvFrame.Visible = false
end
-- ─ HEADING ─
-- HDG pointer: hdg/360 * aiW
local hdgFrac = hdg / 360
hdgPtr.Position = UDim2.new(hdgFrac, -1, 0, 0)
hdgRead.Text = string.format("%03.0f°", hdg)
ndHdgLbl.Text = string.format("%03.0f°", hdg)
-- ─ ND NEEDLE ─
-- Needle rotasyon: hdg derece döner
-- Roblox'ta rotation ile basit oku göster
-- (Frame rotation olmadığı için sadece konumu güncelliyoruz)
-- ─ TOPSTRIP ─
pitchRead.Text = string.format("PTH %+.1f°", pitch)
vsRead.Text = string.format("V/S %+d fpm", vs)
-- ─ BAR ─
barVals.gs.Text = tostring(gs) .. " kts"
barVals.vs.Text = (vs >= 0 and "+" or "") .. tostring(vs) .. " fpm"
barVals.phase.Text = AP.phase
-- Dist
local dist = "---"
if AP.arrRunway then
dist = tostring(math.floor(dist2D(hrp.Position, AP.arrRunway.threshold))) .. " st"
end
barVals.dist.Text = dist
-- WP
barVals.wp.Text = AP.active and (tostring(wpIndex).."/"..tostring(#waypoints)) or "-/-"
-- DEP/ARR
barVals.dep.Text = AP.depRunway and AP.depRunway.name or "---"
barVals.arr.Text = AP.arrRunway and AP.arrRunway.name or "---"
-- ─ ND ─
local dStr = AP.arrRunway
and tostring(math.floor(dist2D(hrp.Position, AP.arrRunway.threshold)))
or "---"
ndDestLbl.Text = "DEST: " .. dStr .. " stud"
ndWPLbl.Text = "WP: " .. (AP.active and (tostring(wpIndex).."/"..tostring(#waypoints)) or "-/-")
local phColor = AP.active and C.green or C.red
ndPhaseLbl.Text = AP.phase
ndPhaseLbl.TextColor3 = phColor
prevAlt = alt
end)
end)
print("✅ PTFS Autopilot v15 yüklendi!")
print(" Sağda PTFS v15 paneli | ☰ Menü | ✈ AP | 🖥 Kokpit")No comments yet for this script.