-- ╔══════════════════════════════════════════════════════╗ -- ║ 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")