--====================================================================================
-- ATC script made by GlitchDetector for Transport Tycoon
-- Original Menu Script Author: Jonathan D @ Gannon
-- https://www.twitch.tv/n3mtv
-- https://twitter.com/n3m_tv
-- https://www.facebook.com/lan3mtv
--====================================================================================
function landMenu(data)
for k,v in next, data do
Citizen.Trace(tostring(k) .. ": " .. tostring(v))
end
TriggerEvent('chatMessage', "", {255, 0, 0}, "Function call: " .. data.Title)
if data.extraData ~= nil then
TriggerEvent('chatMessage', "", {255, 0, 0}, "extraData : " .. data.extraData)
end
end
function takeoffMenu(data)
landMenu(data)
end
function takeoffMarker(pos)
createFlashingBlip(pos, 549, 30)
end
function landMarker(pos)
createFlashingBlip(pos, 556, 30)
end
function createFlashingBlip(pos, blipid, time, col, override)
TriggerServerEvent('atc:flashingBlip', pos, blipid, time, col or 46, override or 0)
end
function callATC(region, method, runway, p4, override)
local msg = "^1%s ATC: ^r^3%s ^0is preparing ^1%s ^r^0at runway ^2%s"
if p4 or 0 then
msg = "^1%s ATC: ^r^3%s ^0is preparing ^1%s ^r^0at ^2%s"
end
local name = GetPlayerName(PlayerId())
msg = string.format(msg, region, name, method, runway)
TriggerServerEvent('atc:message', msg, override or 0)
end
function takeoffLSIA(data)
takeoffMarker(data.extraData.pos)
callATC("L.S.I.A", "takeoff", data.extraData.runway)
end
function takeoffSandy(data)
takeoffMarker(data.extraData.pos)
callATC("Sandy Shores", "takeoff", data.extraData.runway)
end
function takeoffZancudo(data)
takeoffMarker(data.extraData.pos)
callATC("Zancudo", "takeoff", data.extraData.runway)
end
function takeoffMcKenzie(data)
takeoffMarker(data.extraData.pos)
callATC("McKenzie", "takeoff", data.extraData.runway)
end
function takeoffPaleto(data)
takeoffMarker(data.extraData.pos)
callATC("Paleto Bay", "takeoff", data.extraData.runway)
end
function takeoffPacific(data)
takeoffMarker(data.extraData.pos)
callATC("Pacific Ocean", "takeoff", data.extraData.runway)
end
function takeoffCarrier(data)
takeoffMarker(data.extraData.pos)
callATC("Aircraft Carrier", "takeoff", data.extraData.runway)
end
-- LANDING
function landLSIA(data)
landMarker(data.extraData.pos)
callATC("L.S.I.A", "to land", data.extraData.runway)
end
function landSandy(data)
landMarker(data.extraData.pos)
callATC("Sandy Shores", "to land", data.extraData.runway)
end
function landZancudo(data)
landMarker(data.extraData.pos)
callATC("Zancudo", "to land", data.extraData.runway)
end
function landMcKenzie(data)
landMarker(data.extraData.pos)
callATC("McKenzie", "to land", data.extraData.runway)
end
function landPaleto(data)
landMarker(data.extraData.pos)
callATC("Paleto Bay", "to land", data.extraData.runway)
end
function landPacific(data)
landMarker(data.extraData.pos)
callATC("Pacific Ocean", "to land", data.extraData.runway)
end
function landCarrier(data)
landMarker(data.extraData.pos)
callATC("Aircraft Carrier", "to land", data.extraData.runway)
end
function sendLocation()
local pos = GetEntityCoords(GetPlayerPed(-1))
pos = {x=pos.x,y=pos.y,z=pos.z}
createFlashingBlip(pos, 307, 30, 4)
end
function emergencyLanding()
local pos = GetEntityCoords(GetPlayerPed(-1))
callATC("Emergency", "emergency landing", string.format("%i°N %i°E", math.floor(pos.y), math.floor(pos.x)), 0, true)
pos = {x=pos.x,y=pos.y,z=pos.z}
createFlashingBlip(pos, 556, 30, true)
end
function mayday()
local pos = GetEntityCoords(GetPlayerPed(-1))
callATC("Emergency", "emergency landing", string.format("%i°N %i°E", math.floor(pos.y), math.floor(pos.x)), 0, true)
pos = {x=pos.x,y=pos.y,z=pos.z}
createFlashingBlip(pos, 556, 30, true, true)
end
--====================================================================================
-- Build Menu
--====================================================================================
Menu = {}
Menu.item = {
['Title'] = 'ATC Menu',
['Items'] = {
{['Title'] = 'L.S.I.A', ['SubMenu'] = {
['Title'] = 'ATC L.S.I.A',
['Items'] = {
{ ['Title'] = '~g~Land ~y~3 / 21 ~b~(Jet)', ['Function'] = landLSIA, ['extraData'] = {runway = '3 / 21 (JET)', pos = {x = -1484.241333, y = -2467.335449, z = 12.945147}} },
{ ['Title'] = '~g~Land ~y~30R / 12L ~r~(Main)', ['Function'] = landLSIA, ['extraData'] = {runway = '30R / 12L (MAIN)', pos = {x = -1291.800293, y = -2973.775635, z = 12.944430}} },
{ ['Title'] = '~g~Land ~y~30L / 12R ~g~(Side)', ['Function'] = landLSIA, ['extraData'] = {runway = '30L / 12R (SIDE)', pos = {x = -1386.934204, y = -3114.256836, z = 12.944432}} },
{ ['Title'] = '~b~Takeoff ~y~3 / 21 ~b~(Jet)', ['Function'] = takeoffLSIA, ['extraData'] = {runway = '3 / 21 (JET)', pos = {x = -1484.241333, y = -2467.335449, z = 12.945147}} },
{ ['Title'] = '~b~Takeoff ~y~30R / 12L ~r~(Main)', ['Function'] = takeoffLSIA, ['extraData'] = {runway = '30R / 12L (MAIN)', pos = {x = -1291.800293, y = -2973.775635, z = 12.944430}} },
{ ['Title'] = '~b~Takeoff ~y~30L / 12R ~g~(Side)', ['Function'] = takeoffLSIA, ['extraData'] = {runway = '30L / 12R (SIDE)', pos = {x = -1386.934204, y = -3114.256836, z = 12.944432}} },
}
}},
{['Title'] = 'Sandy Shores', ['SubMenu'] = {
['Title'] = 'ATC Sandy Shores',
['Items'] = {
{ ['Title'] = '~g~Land ~y~5 / 23 ~b~(Jet)', ['Function'] = landSandy, ['extraData'] = {runway = '5 / 23 (JET)', pos = {x = 1500.337769, y = 3094.885986, z = 39.531616}} },
{ ['Title'] = '~g~Land ~y~26L / 8R ~g~(Side)', ['Function'] = landSandy, ['extraData'] = {runway = '26L / 8R (SIDE)', pos = {x = 1354.870361, y = 3088.605713, z = 39.534142}} },
{ ['Title'] = '~g~Land ~y~26R / 8L ~r~(Main)', ['Function'] = landSandy, ['extraData'] = {runway = '26R / 8L (MAIN)', pos = {x = 1337.828125, y = 3151.860107, z = 39.414097}} },
{ ['Title'] = '~b~Takeoff ~y~5 / 23 ~b~(Jet)', ['Function'] = takeoffSandy, ['extraData'] = {runway = '5 / 23 (JET)', pos = {x = 1500.337769, y = 3094.885986, z = 39.531616}} },
{ ['Title'] = '~b~Takeoff ~y~26L / 8R ~g~(Side)', ['Function'] = takeoffSandy, ['extraData'] = {runway = '26L / 8R (SIDE)', pos = {x = 1354.870361, y = 3088.605713, z = 39.534142}} },
{ ['Title'] = '~b~Takeoff ~y~26R / 8L ~r~(Main)', ['Function'] = takeoffSandy, ['extraData'] = {runway = '26R / 8L (MAIN)', pos = {x = 1337.828125, y = 3151.860107, z = 39.414097}} },
}
}},
{['Title'] = 'Zancudo', ['SubMenu'] = {
['Title'] = 'ATC Zancudo',
['Items'] = {
{ ['Title'] = '~g~Land ~y~33 / 15 ~b~(Jet)', ['Function'] = landZancudo, ['extraData'] = {runway = '33 / 15 (JET)', pos = {x = -2480.605225, y = 3235.851807, z = 31.925560}} },
{ ['Title'] = '~g~Land ~y~30 / 12 ~r~(Main)', ['Function'] = landZancudo, ['extraData'] = {runway = '30 / 12 (MAIN)', pos = {x = -2375.579834, y = 3070.625732, z = 31.825928}} },
{ ['Title'] = '~b~Takeoff ~y~33 / 15 ~b~(Jet)', ['Function'] = takeoffZancudo, ['extraData'] = {runway = '33 / 15 (JET)', pos = {x = -2480.605225, y = 3235.851807, z = 31.925560}} },
{ ['Title'] = '~b~Takeoff ~y~30 / 12 ~r~(Main)', ['Function'] = takeoffZancudo, ['extraData'] = {runway = '30 / 12 (MAIN)', pos = {x = -2375.579834, y = 3070.625732, z = 31.825928}} },
}
}},
{['Title'] = 'McKenzie', ['SubMenu'] = {
['Title'] = 'ATC McKenzie',
['Items'] = {
{ ['Title'] = '~g~Land ~y~25 / 7', ['Function'] = landMcKenzie, ['extraData'] = {runway = '25 / 7', pos = {x = 2030.718628, y = 4755.413574, z = 40.124157}} },
{ ['Title'] = '~b~Takeoff ~y~25 / 7', ['Function'] = takeoffMcKenzie, ['extraData'] = {runway = '25 / 7', pos = {x = 2030.718628, y = 4755.413574, z = 40.124157}} },
}
}},
{['Title'] = 'Paleto Bay', ['SubMenu'] = {
['Title'] = 'ATC Paleto Bay',
['Items'] = {
{ ['Title'] = '~g~Land ~y~5 / 23 ~b~(Jet)', ['Function'] = landPaleto, ['extraData'] = {runway = '5 / 23 (JET)', pos = {x = -380.410980, y = 6497.020508, z = 7.386814}} },
{ ['Title'] = '~g~Land ~y~7 / 25 ~r~(Main)', ['Function'] = landPaleto, ['extraData'] = {runway = '7 / 25 (MAIN)', pos = {x = -587.827454, y = 6474.951660, z = 6.639785}} },
{ ['Title'] = '~b~Takeoff ~y~5 / 23 ~b~(Jet)', ['Function'] = takeoffPaleto, ['extraData'] = {runway = '5 / 23 (JET)', pos = {x = -380.410980, y = 6497.020508, z = 7.386814}} },
{ ['Title'] = '~b~Takeoff ~y~7 / 25 ~r~(Main)', ['Function'] = takeoffPaleto, ['extraData'] = {runway = '7 / 25 (MAIN)', pos = {x = -587.827454, y = 6474.951660, z = 6.639785}} },
}
}},
{['Title'] = 'Pacific Ocean', ['SubMenu'] = {
['Title'] = 'ATC Pacific Ocean',
['Items'] = {
{ ['Title'] = '~g~Land ~y~17 / 35 ~b~(Jet)', ['Function'] = landPacific, ['extraData'] = {runway = '17 / 35 (JET)', pos = {x = 2907.530273, y = -980.678345, z = 7.899795}} },
{ ['Title'] = '~g~Land ~y~18 / ~y~36 ~r~(Main)', ['Function'] = landPacific, ['extraData'] = {runway = '18 / 36 (MAIN)', pos = {x = 2996.983398, y = -992.581482, z = 7.899790}} },
{ ['Title'] = '~g~Land ~y~9 / ~y~27 ~g~(Side)', ['Function'] = landPacific, ['extraData'] = {runway = '9 / 27 (SIDE)', pos = {x = 3310.866455, y = -822.977173, z = 7.889794}} },
{ ['Title'] = '~g~Land ~y~4 / ~y~22 ~g~(Diagonal)', ['Function'] = landPacific, ['extraData'] = {runway = '4 / 22 (DIAG)', pos = {x = 3261.814941, y = -676.519897, z = 7.889794}} },
{ ['Title'] = '~b~Takeoff ~y~17 / 35 ~b~(Jet)', ['Function'] = takeoffPacific, ['extraData'] = {runway = '17 / 35 (JET)', pos = {x = 2907.530273, y = -980.678345, z = 7.899795}} },
{ ['Title'] = '~b~Takeoff ~y~18 / 36 ~r~(Main)', ['Function'] = takeoffPacific, ['extraData'] = {runway = '18 / 36 (MAIN)', pos = {x = 2996.983398, y = -992.581482, z = 7.899790}} },
{ ['Title'] = '~b~Takeoff ~y~9 / 27 ~b~(Side)', ['Function'] = takeoffPacific, ['extraData'] = {runway = '9 / 27 (SIDE)', pos = {x = 3310.866455, y = -822.977173, z = 7.889794}} },
{ ['Title'] = '~b~Takeoff ~y~4 / 22 ~b~(Diagonal)', ['Function'] = takeoffPacific, ['extraData'] = {runway = '4 / 22 (DIAG)', pos = {x = 3261.814941, y = -676.519897, z = 7.889794}} },
}
}},
{['Title'] = 'Aircraft Carrier', ['SubMenu'] = {
['Title'] = 'ATC Carrier',
['Items'] = {
{ ['Title'] = '~g~Land ~y~CV-96', ['Function'] = landCarrier, ['extraData'] = {runway = 'CV-96', pos = {x = 3049.651367, y = -4702.908691, z = 13.837625}} },
{ ['Title'] = '~b~Takeoff ~y~CV-96', ['Function'] = takeoffCarrier, ['extraData'] = {runway = 'CV-96', pos = {x = 3049.651367, y = -4702.908691, z = 13.837625}} }
}
}},
{['Title'] = '~y~Misc ATC', ['SubMenu'] = {
['Title'] = 'Misc ATC',
['Items'] = {
{ ['Title'] = 'Broadcast Location', ['Function'] = sendLocation},
{ ['Title'] = '~y~Emergency Landing', ['Function'] = emergencyLanding},
{ ['Title'] = '~r~Mayday', ['Function'] = mayday},
}
}},
}
}
--====================================================================================
-- Option Menu
--====================================================================================
Menu.backgroundColor = { 52, 73, 94, 196 }
Menu.backgroundColorActive = { 22, 160, 134, 255 }
Menu.tileTextColor = { 22, 160, 134, 255 }
Menu.tileBackgroundColor = { 255,255,255, 255 }
Menu.textColor = { 255,255,255,255 }
Menu.textColorActive = { 255,255,255, 255 }
Menu.keyOpenMenu = 99 -- TAB
Menu.keyOpenMenu2 = 179 -- CONTROLLER SQUARE/X MMB
Menu.keyUp = 172 -- PhoneUp
Menu.keyDown = 173 -- PhoneDown
Menu.keyLeft = 174 -- PhoneLeft || Not use next release Maybe
Menu.keyRight = 175 -- PhoneRigth || Not use next release Maybe
Menu.keySelect = 176 -- PhoneSelect
Menu.KeyCancel = 177 -- PhoneCancel
Menu.posX = 1 - 0.3
Menu.posY = 1 - 0.7
Menu.ItemWidth = 0.20
Menu.ItemHeight = 0.03
Menu.isOpen = false -- /!\ Ne pas toucher
Menu.currentPos = {1} -- /!\ Ne pas toucher
--====================================================================================
-- Menu System
--====================================================================================
function Menu.drawRect(posX, posY, width, heigh, color)
DrawRect(posX + width / 2, posY + heigh / 2, width, heigh, color[1], color[2], color[3], color[4])
end
function Menu.initText(textColor, font, scale)
font = font or 0
scale = scale or 0.35
SetTextFont(font)
SetTextScale(0.0,scale)
SetTextCentre(true)
SetTextDropShadow(0, 0, 0, 0, 0)
SetTextEdge(0, 0, 0, 0, 0)
SetTextColour(textColor[1], textColor[2], textColor[3], textColor[4])
SetTextEntry("STRING")
end
function Menu.draw()
-- Draw Rect
local pos = 0
local menu = Menu.getCurrentMenu()
local selectValue = Menu.currentPos[#Menu.currentPos]
local nbItem = #menu.Items
-- draw background title & title
Menu.drawRect(Menu.posX, Menu.posY , Menu.ItemWidth, Menu.ItemHeight * 2, Menu.tileBackgroundColor)
Menu.initText(Menu.tileTextColor, 4, 0.7)
AddTextComponentString(menu.Title)
DrawText(Menu.posX + Menu.ItemWidth/2, Menu.posY)
-- draw bakcground items
Menu.drawRect(Menu.posX, Menu.posY + Menu.ItemHeight * 2, Menu.ItemWidth, Menu.ItemHeight + (nbItem-1)*Menu.ItemHeight, Menu.backgroundColor)
-- draw all items
for pos, value in pairs(menu.Items) do
if pos == selectValue then
Menu.drawRect(Menu.posX, Menu.posY + Menu.ItemHeight * (1+pos), Menu.ItemWidth, Menu.ItemHeight, Menu.backgroundColorActive)
Menu.initText(Menu.textColorActive)
else
Menu.initText(Menu.textColor)
end
AddTextComponentString(value.Title)
DrawText(Menu.posX + Menu.ItemWidth/2, Menu.posY + Menu.ItemHeight * (pos+1))
end
end
function Menu.getCurrentMenu()
local currentMenu = Menu.item
for i=1, #Menu.currentPos - 1 do
local val = Menu.currentPos[i]
currentMenu = currentMenu.Items[val].SubMenu
end
return currentMenu
end
function Menu.initMenu()
Menu.currentPos = {1}
end
function Menu.keyControl()
if IsControlJustPressed(1, Menu.keyDown) then
local cMenu = Menu.getCurrentMenu()
local size = #cMenu.Items
local slcp = #Menu.currentPos
Menu.currentPos[slcp] = (Menu.currentPos[slcp] % size) + 1
elseif IsControlJustPressed(1, Menu.keyUp) then
local cMenu = Menu.getCurrentMenu()
local size = #cMenu.Items
local slcp = #Menu.currentPos
Menu.currentPos[slcp] = ((Menu.currentPos[slcp] - 2 + size) % size) + 1
elseif IsControlJustPressed(1, Menu.KeyCancel) then
table.remove(Menu.currentPos)
if #Menu.currentPos == 0 then
Menu.isOpen = false
end
elseif IsControlJustPressed(1, Menu.keySelect) then
local cSelect = Menu.currentPos[#Menu.currentPos]
local cMenu = Menu.getCurrentMenu()
if cMenu.Items[cSelect].SubMenu ~= nil then
Menu.currentPos[#Menu.currentPos + 1] = 1
else
if cMenu.Items[cSelect].Function ~= nil then
cMenu.Items[cSelect].Function(cMenu.Items[cSelect])
end
if cMenu.Items[cSelect].Event ~= nil then
TriggerEvent(cMenu.Items[cSelect].Event, cMenu.Items[cSelect])
end
if cMenu.Items[cSelect].Close == nil or cMenu.Items[cSelect].Close == true then
Menu.isOpen = false
end
end
end
end
Citizen.CreateThread(function()
while true do
Citizen.Wait(1)
if IsPedInAnyPlane(GetPlayerPed(-1)) or IsPedInAnyHeli(GetPlayerPed(-1)) then
if IsControlJustPressed(1, Menu.keyOpenMenu) then
Menu.initMenu()
Menu.isOpen = not Menu.isOpen
end
if Menu.isOpen then
Menu.draw()
Menu.keyControl()
end
end
end
end)
RegisterNetEvent("atc:startFlashingBlip")
AddEventHandler("atc:startFlashingBlip", function(pos, blipid, time, col, override)
if IsPedInAnyPlane(GetPlayerPed(-1)) or IsPedInAnyHeli(GetPlayerPed(-1)) or (override) then
local blip = AddBlipForCoord(pos.x, pos.y, pos.z)
SetBlipSprite(blip, blipid)
SetBlipColour(blip, col)
SetBlipDisplay(blip, 8)
SetBlipFlashes(blip, true)
SetBlipFlashInterval(blip, 400)
SetTimeout(time * 1000, function()
RemoveBlip(blip)
end)
end
end)
RegisterNetEvent("atc:getMessage")
AddEventHandler("atc:getMessage", function(msg, override)
if IsPedInAnyPlane(GetPlayerPed(-1)) or IsPedInAnyHeli(GetPlayerPed(-1)) or (override) then
TriggerEvent('chatMessage', "", {255, 0, 0}, msg)
end
end)
RegisterNetEvent("atc:warning")
AddEventHandler("atc:warning", function()
msg = "~r~ATC WARNING:~y~ Your callout conflicts with another player's. ~n~Please make a visual check before proceeding."
Citizen.Trace("Received ATC warning")
TriggerEvent("gd_utils:oneliner", msg, 10)
end)
Citizen.CreateThread(function()
local inAircraft = false
while true do
Wait(50)
if not inAircraft and (IsPedInAnyPlane(GetPlayerPed(-1)) or IsPedInAnyHeli(GetPlayerPed(-1))) then
SetNotificationTextEntry("STRING")
AddTextComponentString("~w~Press ~g~TAB ~w~to open the ~y~ATC menu~w~.\nIt's ~r~mandatory ~w~to use when piloting!")
DrawNotification(false, false)
end
inAircraft = (IsPedInAnyPlane(GetPlayerPed(-1)) or IsPedInAnyHeli(GetPlayerPed(-1)))
end
end)
Comments