From cae208fef5eab453c2a35e3f9059969be4482179 Mon Sep 17 00:00:00 2001 From: Pickle <111543470+PickleModifications@users.noreply.github.com> Date: Tue, 29 Nov 2022 23:45:54 -0500 Subject: [PATCH] Add files via upload --- __INSTALLATION/Jobs/esx.sql | 6 + __INSTALLATION/Jobs/qbcore.lua | 25 +++ bridge/esx/client.lua | 32 ++++ bridge/esx/server.lua | 61 +++++++ bridge/qb/client.lua | 38 ++++ bridge/qb/server.lua | 60 +++++++ bridge/standalone/client.lua | 4 + bridge/standalone/server.lua | 4 + config.lua | 223 +++++++++++++++++++++++ core/client.lua | 66 +++++++ core/server.lua | 0 core/shared.lua | 24 +++ fxmanifest.lua | 24 +++ modules/airports/client.lua | 313 +++++++++++++++++++++++++++++++++ modules/airports/server.lua | 59 +++++++ modules/missions/client.lua | 278 +++++++++++++++++++++++++++++ modules/missions/server.lua | 13 ++ modules/tracker/client.lua | 56 ++++++ modules/tracker/server.lua | 15 ++ 19 files changed, 1301 insertions(+) create mode 100644 __INSTALLATION/Jobs/esx.sql create mode 100644 __INSTALLATION/Jobs/qbcore.lua create mode 100644 bridge/esx/client.lua create mode 100644 bridge/esx/server.lua create mode 100644 bridge/qb/client.lua create mode 100644 bridge/qb/server.lua create mode 100644 bridge/standalone/client.lua create mode 100644 bridge/standalone/server.lua create mode 100644 config.lua create mode 100644 core/client.lua create mode 100644 core/server.lua create mode 100644 core/shared.lua create mode 100644 fxmanifest.lua create mode 100644 modules/airports/client.lua create mode 100644 modules/airports/server.lua create mode 100644 modules/missions/client.lua create mode 100644 modules/missions/server.lua create mode 100644 modules/tracker/client.lua create mode 100644 modules/tracker/server.lua diff --git a/__INSTALLATION/Jobs/esx.sql b/__INSTALLATION/Jobs/esx.sql new file mode 100644 index 0000000..3e4469f --- /dev/null +++ b/__INSTALLATION/Jobs/esx.sql @@ -0,0 +1,6 @@ +INSERT INTO `jobs` (`name`, `label`, `whitelisted`) VALUES ('airport', 'Airport', '1'); + +INSERT INTO `job_grades` (`job_name`, `grade`, `name`, `label`, `salary`, `skin_male`, `skin_female`) VALUES ('airport', '0', 'recruit', 'Recruit', '0', '{}', '{}'); +INSERT INTO `job_grades` (`job_name`, `grade`, `name`, `label`, `salary`, `skin_male`, `skin_female`) VALUES ('airport', '0', 'employee', 'Pilot', '0', '{}', '{}'); +INSERT INTO `job_grades` (`job_name`, `grade`, `name`, `label`, `salary`, `skin_male`, `skin_female`) VALUES ('airport', '0', 'manager', 'Lead Pilot', '0', '{}', '{}'); +INSERT INTO `job_grades` (`job_name`, `grade`, `name`, `label`, `salary`, `skin_male`, `skin_female`) VALUES ('airport', '0', 'boss', 'Air-Traffic Controller', '0', '{}', '{}'); diff --git a/__INSTALLATION/Jobs/qbcore.lua b/__INSTALLATION/Jobs/qbcore.lua new file mode 100644 index 0000000..0bba379 --- /dev/null +++ b/__INSTALLATION/Jobs/qbcore.lua @@ -0,0 +1,25 @@ +['airport'] = { + label = 'Airport', + defaultDuty = true, + offDutyPay = false, + grades = { + ['0'] = { + name = 'Recruit', + payment = 0 + }, + ['1'] = { + name = 'Pilot', + payment = 0 + }, + ['2'] = { + name = 'Lead Pilot', + payment = 0 + }, + ['3'] = { + name = 'Air-Traffic Controller', + isboss = true, + bankAuth = true, + payment = 0 + }, + }, +}, \ No newline at end of file diff --git a/bridge/esx/client.lua b/bridge/esx/client.lua new file mode 100644 index 0000000..0dd11ed --- /dev/null +++ b/bridge/esx/client.lua @@ -0,0 +1,32 @@ +if GetResourceState('es_extended') ~= 'started' then return end + +ESX = exports.es_extended:getSharedObject() + +function ShowNotification(text) + ESX.ShowNotification(text) +end + +function ShowHelpNotification(text) + ESX.ShowHelpNotification(text) +end + +function ServerCallback(name, cb, ...) + ESX.TriggerServerCallback(name, cb, ...) +end + +function PermissionCheck(perm) + local job = ESX.GetPlayerData().job + if (perm == "flight") then + return (job.name == "airport") + elseif (perm == "hangar") then + return (job.name == "airport") + elseif (perm == "pilot_mission") then + return (job.name == "airport") + elseif (perm == "view_tracker") then + return (job.name == "airport" or job.name == "police") + end +end + +RegisterNetEvent(GetCurrentResourceName()..":showNotification", function(text) + ShowNotification(text) +end) \ No newline at end of file diff --git a/bridge/esx/server.lua b/bridge/esx/server.lua new file mode 100644 index 0000000..7fde73e --- /dev/null +++ b/bridge/esx/server.lua @@ -0,0 +1,61 @@ +if GetResourceState('es_extended') ~= 'started' then return end + +ESX = exports.es_extended:getSharedObject() + +function RegisterCallback(name, cb) + ESX.RegisterServerCallback(name, cb) +end + +function ShowNotification(target, text) + TriggerClientEvent(GetCurrentResourceName()..":showNotification", target, text) +end + +function Search(source, name) + local xPlayer = ESX.GetPlayerFromId(source) + if (name ~= "money") then + local item = xPlayer.getInventoryItem(name) + if item ~= nil then + return item.count + else + return 0 + end + else + return xPlayer.getMoney() + end +end + +function AddItem(source, name, amount) + local xPlayer = ESX.GetPlayerFromId(source) + if name == "money" then + return xPlayer.addMoney(amount) + else + return xPlayer.addInventoryItem(name, amount) + end +end + +function RemoveItem(source, name, amount) + local xPlayer = ESX.GetPlayerFromId(source) + if name == "money" then + return xPlayer.removeMoney(amount) + else + return xPlayer.removeInventoryItem(name, amount) + end +end + +function CanCarryItem(source, name, amount) + local xPlayer = ESX.GetPlayerFromId(source) + return xPlayer.canCarryItem(name, amount) +end + +function RegisterUsableItem(...) + ESX.RegisterUsableItem(...) +end + +function PermissionCheck(source, perm) + local job = ESX.GetPlayerFromId(source).job + if (perm == "flight") then + return (job.name == "airport") + elseif (perm == "pilot_mission") then + return (job.name == "airport") + end +end \ No newline at end of file diff --git a/bridge/qb/client.lua b/bridge/qb/client.lua new file mode 100644 index 0000000..263cf20 --- /dev/null +++ b/bridge/qb/client.lua @@ -0,0 +1,38 @@ +if GetResourceState('qb-core') ~= 'started' then return end + +QBCore = exports['qb-core']:GetCoreObject() + +function ShowNotification(text) + QBCore.Functions.Notify(text) +end + +function ShowHelpNotification(text) + AddTextEntry('qbHelpNotification', text) + BeginTextCommandDisplayHelp('qbHelpNotification') + EndTextCommandDisplayHelp(0, false, false, -1) +end + +function ServerCallback(name, cb, ...) + QBCore.Functions.TriggerCallback(name, cb, ...) +end + +RegisterNetEvent(GetCurrentResourceName()..":showNotification", function(text) + ShowNotification(text) +end) + +function PermissionCheck(perm) + local job = QBCore.Functions.GetPlayerData().job + if (perm == "flight") then + return (job.name == "airport") + elseif (perm == "hangar") then + return (job.name == "airport") + elseif (perm == "pilot_mission") then + return (job.name == "airport") + elseif (perm == "view_tracker") then + return (job.name == "airport" or job.name == "police") + end +end + +RegisterNetEvent(GetCurrentResourceName()..":showNotification", function(text) + ShowNotification(text) +end) \ No newline at end of file diff --git a/bridge/qb/server.lua b/bridge/qb/server.lua new file mode 100644 index 0000000..17e0162 --- /dev/null +++ b/bridge/qb/server.lua @@ -0,0 +1,60 @@ +if GetResourceState('qb-core') ~= 'started' then return end + +QBCore = exports['qb-core']:GetCoreObject() + +function RegisterCallback(name, cb) + QBCore.Functions.CreateCallback(name, cb) +end + +function ShowNotification(target, text) + TriggerClientEvent(GetCurrentResourceName()..":showNotification", target, text) +end + +function Search(source, name) + local xPlayer = QBCore.Functions.GetPlayer(source) + if name ~= "money" then + local item = xPlayer.Functions.GetItemByName(name) + if item ~= nil then + return item.amount + else + return 0 + end + else + return xPlayer.PlayerData.money['cash'] + end +end + +function AddItem(source, name, amount) + local xPlayer = QBCore.Functions.GetPlayer(source) + if name == "money" then + return xPlayer.Functions.AddMoney("cash", amount) + else + return xPlayer.Functions.AddItem(name, amount) + end +end + +function RemoveItem(source, name, amount) + local xPlayer = QBCore.Functions.GetPlayer(source) + if name == "money" then + return xPlayer.Functions.RemoveMoney("cash", amount) + else + return xPlayer.Functions.RemoveItem(name, amount) + end +end + +function CanCarryItem(source, name, amount) + return true -- No function for this. +end + +function RegisterUsableItem(...) + QBCore.Functions.CreateUseableItem(...) +end + +function PermissionCheck(source, perm) + local job = QBCore.Functions.GetPlayer(source).job + if (perm == "flight") then + return (job.name == "airport") + elseif (perm == "pilot_mission") then + return (job.name == "airport") + end +end \ No newline at end of file diff --git a/bridge/standalone/client.lua b/bridge/standalone/client.lua new file mode 100644 index 0000000..f777178 --- /dev/null +++ b/bridge/standalone/client.lua @@ -0,0 +1,4 @@ +if GetResourceState('es_extended') == 'started' then return end +if GetResourceState('qb-core') == 'started' then return end + +print("You are not using a supported framework, it will be required to make edits to the bridge files.") \ No newline at end of file diff --git a/bridge/standalone/server.lua b/bridge/standalone/server.lua new file mode 100644 index 0000000..f777178 --- /dev/null +++ b/bridge/standalone/server.lua @@ -0,0 +1,4 @@ +if GetResourceState('es_extended') == 'started' then return end +if GetResourceState('qb-core') == 'started' then return end + +print("You are not using a supported framework, it will be required to make edits to the bridge files.") \ No newline at end of file diff --git a/config.lua b/config.lua new file mode 100644 index 0000000..2136796 --- /dev/null +++ b/config.lua @@ -0,0 +1,223 @@ +Config = {} + +Config.Debug = true + +Config.Blips = {} + +Config.Tracker = { + UpdateTime = 10, + BlipTypes = { + { -- Plane + Label = "Plane", + ID = 423, + Color = 38, + Scale = 0.75, + }, + { -- Helicopter + Label = "Helicopter", + ID = 64, + Color = 38, + Scale = 0.75, + }, + } +} + +Config.Missions = { + Blips = { + PackagePickup = { + Label = "Pickup Package", + ID = 569, + Color = 5, + Scale = 0.75 + }, + PackageDropoff = { + Label = "Drop-off Package", + ID = 569, + Color = 5, + Scale = 0.75 + }, + PassengerPickup = { + Label = "Pickup Passengers", + ID = 569, + Color = 5, + Scale = 0.75 + }, + PassengerDropoff = { + Label = "Drop-off Passengers", + ID = 569, + Color = 5, + Scale = 0.75 + }, + }, + Sequences = { + { + Type = "Passenger", + PassengerPickup = vector3(-1215.0138, -2647.5029, 14.5475), + PassengerDropoff = vector3(1713.7322, 3253.1628, 41.6815), + Rewards = { + {name = "money", min = 300, max = 500} + } + }, + { + Type = "Passenger", + PassengerPickup = vector3(1713.7322, 3253.1628, 41.6815), + PassengerDropoff = vector3(-1215.0138, -2647.5029, 14.5475), + Rewards = { + {name = "money", min = 300, max = 500} + } + }, + { + Type = "Passenger", + PassengerPickup = vector3(-1215.0138, -2647.5029, 14.5475), + PassengerDropoff = vector3(2124.8884, 4804.3428, 41.7431), + Rewards = { + {name = "money", min = 300, max = 500} + } + }, + { + Type = "Passenger", + PassengerPickup = vector3(2124.8884, 4804.3428, 41.7431), + PassengerDropoff = vector3(-1215.0138, -2647.5029, 14.5475), + Rewards = { + {name = "money", min = 300, max = 500} + } + }, + { + Type = "Delivery", + PackagePickup = vector3(-940.9973, -2954.2285, 13.9450), + PackageDropoff = vector3(1720.2944, 3306.6436, 41.2235), + Rewards = { + {name = "money", min = 300, max = 500} + } + }, + { + Type = "Delivery", + PackagePickup = vector3(1720.2944, 3306.6436, 41.2235), + PackageDropoff = vector3(-940.9973, -2954.2285, 13.9450), + Rewards = { + {name = "money", min = 300, max = 500} + } + }, + { + Type = "Delivery", + PackagePickup = vector3(-940.9973, -2954.2285, 13.9450), + PackageDropoff = vector3(2137.6079, 4791.4370, 40.9703), + Rewards = { + {name = "money", min = 300, max = 500} + } + }, + { + Type = "Delivery", + PackagePickup = vector3(2137.6079, 4791.4370, 40.9703), + PackageDropoff = vector3(-940.9973, -2954.2285, 13.9450), + Rewards = { + {name = "money", min = 300, max = 500} + } + }, + } +} + +Config.Airports = { + { + AirportTitle = "LSIA Airport", + Blips = { + Boarding = { + Label = "Airport", + ID = 423, + Color = 5, + Scale = 0.75 + } + }, + Locations = { + Boarding = vector3(-1042.4271, -2745.5457, 21.3594), + Flight = vector3(-1287.2458, -2599.4785, 14.5466), + Hangar = vector4(-1058.8749, -2963.2598, 13.9645, 147.2194), + }, + }, + { + AirportTitle = "Sandy Airfield", + Blips = { + Boarding = { + Label = "Airport", + ID = 423, + Color = 5, + Scale = 0.75 + } + }, + Locations = { + Boarding = vector3(1768.0939, 3296.6040, 41.1809), + Flight = vector3(1740.0123, 3282.0764, 41.0884), + Hangar = vector4(1766.9825, 3245.4485, 41.8806, 14.1263), + }, + }, + { + AirportTitle = "Grapeseed Airfield", + Blips = { + Boarding = { + Label = "Airport", + ID = 423, + Color = 5, + Scale = 0.75 + } + }, + Locations = { + Boarding = vector3(2159.0381, 4782.0737, 41.9610), + Flight = vector3(2140.8184, 4815.4282, 41.2161), + Hangar = vector4(2149.6863, 4808.7354, 41.1853, 107.2027), + }, + }, +} + +Config.AirportSettings = { + DepartureTime = 20, + NPCFlightCost = 6500, +} + +Config.Spawner = { + Vehicles = { + {label = "Luxor", description = "", model = `luxor`}, + {label = "Shamal", description = "", model = `shamal`}, + {label = "Cuban 800", description = "", model = `cuban800`}, + {label = "Jet", description = "", model = `jet`}, + {label = "Maverick", description = "", model = `maverick`}, + {label = "Super Volito", description = "", model = `supervolito`}, + } +} + +U = {} + +U.permission_denied = "You can't do this." + +-- Delivery Mission + +U.package_pickup_notify = "Go to the pickup location." +U.package_pickup = "Press ~INPUT_CONTEXT~ to pick up the package." +U.package_load_notify = "Bring the package into the aircraft." +U.package_flight_notify = "Fly the aircraft to the desination." +U.package_dropoff_notify = "Go to the drop-off location." +U.package_dropoff = "Press ~INPUT_CONTEXT~ to drop-off package." + +-- Passenger Mission + +U.passenger_pickup_notify = "Go to the flight terminal." +U.passenger_pickup = "Press ~INPUT_CONTEXT~ to pick up the passengers." +U.passenger_loading = "Loading Passengers..." +U.passenger_unloading = "Unloading Passengers..." +U.passenger_dropoff_notify = "Fly the aircraft to the desination." +U.passenger_dropoff = "Press ~INPUT_CONTEXT~ to drop-off the passengers." + +-- Airport +U.Boarding_interact = "Press ~INPUT_CONTEXT~ to board a flight." +U.Boarding_npc_interact = "Press ~INPUT_CONTEXT~ to fly for: $" +U.Boarding_unavailable = "There are no flights available." +U.Boarding_broke = "You can't afford to purchase this plane ticket." +U.Boarding_full = "You can't join the flight as it is full." + +U.Flight_interact = "Press ~INPUT_CONTEXT~ to start a flight." +U.Flight_return = "Press ~INPUT_CONTEXT~ to drop-off your passengers." +U.Flight_reject = "You need to be in a plane to start a flight." +U.Flight_denied = "You can't do this." + +U.Hangar_interact = "Press ~INPUT_CONTEXT~ to retreive an aircraft." +U.Hangar_return = "Press ~INPUT_CONTEXT~ to return your aircraft." +U.Hangar_denied = "You can't do this." \ No newline at end of file diff --git a/core/client.lua b/core/client.lua new file mode 100644 index 0000000..01b87f5 --- /dev/null +++ b/core/client.lua @@ -0,0 +1,66 @@ +function CreateVeh(modelHash, ...) + RequestModel(modelHash) + while not HasModelLoaded(modelHash) do Wait(0) end + local veh = CreateVehicle(modelHash, ...) + SetModelAsNoLongerNeeded(modelHash) + return veh +end + +function CreateNPC(modelHash, ...) + RequestModel(modelHash) + while not HasModelLoaded(modelHash) do Wait(0) end + local ped = CreatePed(26, modelHash, ...) + SetModelAsNoLongerNeeded(modelHash) + return ped +end + +function CreateProp(modelHash, ...) + RequestModel(modelHash) + while not HasModelLoaded(modelHash) do Wait(0) end + local obj = CreateObject(modelHash, ...) + SetModelAsNoLongerNeeded(modelHash) + return obj +end + +function PlayAnim(ped, dict, ...) + RequestAnimDict(dict) + while not HasAnimDictLoaded(dict) do Wait(0) end + TaskPlayAnim(ped, dict, ...) +end + +function PlayEffect(dict, particleName, entity, off, rot, time, cb) + CreateThread(function() + RequestNamedPtfxAsset(dict) + while not HasNamedPtfxAssetLoaded(dict) do + Wait(0) + end + UseParticleFxAssetNextCall(dict) + Wait(10) + local particleHandle = StartParticleFxLoopedOnEntity(particleName, entity, off.x, off.y, off.z, rot.x, rot.y, rot.z, 1.0) + SetParticleFxLoopedColour(particleHandle, 0, 255, 0 , 0) + Wait(time) + StopParticleFxLooped(particleHandle, false) + cb() + end) +end + +function CreateBlip(data) + local x,y,z = table.unpack(data.Location) + local blip = AddBlipForCoord(x, y, z) + SetBlipSprite(blip, data.ID) + SetBlipDisplay(blip, 4) + SetBlipScale(blip, data.Scale) + SetBlipColour(blip, data.Color) + if (data.Rotation) then + SetBlipRotation(blip, math.ceil(data.Rotation)) + end + SetBlipAsShortRange(blip, true) + BeginTextCommandSetBlipName("STRING") + AddTextComponentString(data.Label) + EndTextCommandSetBlipName(blip) + return blip +end + +for i=1, #Config.Blips do + CreateBlip(Config.Blips[i]) +end \ No newline at end of file diff --git a/core/server.lua b/core/server.lua new file mode 100644 index 0000000..e69de29 diff --git a/core/shared.lua b/core/shared.lua new file mode 100644 index 0000000..0c0501d --- /dev/null +++ b/core/shared.lua @@ -0,0 +1,24 @@ +function lerp(a, b, t) return a + (b-a) * t end + +function v3(coords) return vec3(coords.x, coords.y, coords.z), coords.w end + +function dprint(...) + if Config.Debug then + print(...) + end +end + +function GetRandomInt(min, max, skipNum) + if min >= max then + return min + else + local num = math.random(min, max) + if skipNum ~= nil and skipNum == num then + while skipNum == num do + num = math.random(min, max) + Wait(0) + end + end + return num + end +end \ No newline at end of file diff --git a/fxmanifest.lua b/fxmanifest.lua new file mode 100644 index 0000000..e6d8872 --- /dev/null +++ b/fxmanifest.lua @@ -0,0 +1,24 @@ +fx_version "cerulean" +game "gta5" + +shared_scripts { + "@ox_lib/init.lua", + "config.lua", + "bridge/**/shared.lua", + "modules/**/shared.lua", + "core/shared.lua" +} + +client_scripts { + "bridge/**/client.lua", + "modules/**/client.lua", + "core/client.lua" +} + +server_scripts { + "bridge/**/server.lua", + "modules/**/server.lua", + "core/server.lua" +} + +lua54 'yes' \ No newline at end of file diff --git a/modules/airports/client.lua b/modules/airports/client.lua new file mode 100644 index 0000000..ee09e91 --- /dev/null +++ b/modules/airports/client.lua @@ -0,0 +1,313 @@ +local Interact = false + +function StartNPCFlight(index) + ServerCallback("pickle_airport:startNPCFlight", function(result) + if (result) then + local cfg = Config.Airports[index] + local coords = cfg.Locations.Boarding + local ped = PlayerPedId() + DoScreenFadeOut(1000) + Wait(1500) + SetEntityCoords(ped, coords.x, coords.y, coords.z) + Wait(100) + DoScreenFadeIn(1000) + else + ShowNotification(U.Boarding_broke) + end + Interact = false + end, index) +end + +function JoinActiveFlight(index) + local airport = Config.Airports[index] + if GlobalState.Flights[index] then + local data = GlobalState.Flights[index] + CreateThread(function() + local ped = PlayerPedId() + DoScreenFadeOut(1000) + Wait(1500) + SetEntityCoords(ped, data.coords.x, data.coords.y, data.coords.z + 10.0) + Wait(100) + local vehicle = NetToVeh(data.net_id) + local seats = GetVehicleModelNumberOfSeats(GetEntityModel(vehicle)) - 2 + local found = false + for i=1, seats do + if IsVehicleSeatFree(vehicle, i) then + TaskWarpPedIntoVehicle(ped, vehicle, i) + found = true + break + end + end + if not found then + local coords = airport.Locations.Boarding + SetEntityCoords(ped, coords.x, coords.y, coords.z - 1.0) + Wait(100) + DoScreenFadeIn(1000) + ShowNotification(U.Boarding_full) + else + ServerCallback("pickle_airport:purchaseTicket", function(result) + if (not result) then + local coords = airport.Locations.Boarding + SetEntityCoords(ped, coords.x, coords.y, coords.z - 1.0) + Wait(100) + ShowNotification(U.Boarding_broke) + end + DoScreenFadeIn(1000) + end, index) + end + Interact = false + end) + else + Interact = false + end +end + +function OpenFlightMenu(index, vehicle) + local menu_id = "airport_flight_menu" + local options = {} + for i=1, #Config.Airports do + if index ~= i then + local _index = i + options[#options + 1] = {label = Config.Airports[i].AirportTitle, description = "", index = _index} + end + end + lib.registerMenu({ + id = menu_id, + title = 'Choose Destination', + position = 'top-left', + onClose = function(keyPressed) + Interact = false + end, + options = options + }, function(selected, scrollIndex, args) + Wait(250) + local input = lib.inputDialog('Flight Cost', {'Price'}) + if not input or tonumber(input[1]) == nil then + Interact = false + return + else + local flight_info = {destination = options[selected].index, price = math.ceil(tonumber(input[1])), coords = GetEntityCoords(vehicle), net_id = VehToNet(vehicle)} + ServerCallback("pickle_airport:startFlight", function(result) + if (result) then + ShowNotification("Boarding Players, Takeoff Time: ".. Config.AirportSettings.DepartureTime .. " (s)") + FreezeEntityPosition(vehicle, true) + Wait(1000 * Config.AirportSettings.DepartureTime) + FreezeEntityPosition(vehicle, false) + ShowNotification("Players are now boarded, you are clear for takeoff.") + end + Interact = false + end, index, flight_info) + end + end) + lib.showMenu(menu_id) +end + +function OpenSpawnMenu(index) + local menu_id = "airport_spawn_menu" + local options = Config.Spawner.Vehicles + local cfg = Config.Airports[index] + local coords = cfg.Locations.Hangar + lib.registerMenu({ + id = menu_id, + title = 'Aircraft Spawner', + position = 'top-left', + onClose = function(keyPressed) + Interact = false + end, + options = options + }, function(selected, scrollIndex, args) + local data = options[selected] + local vehicle = CreateVeh(data.model, coords.x, coords.y, coords.z, coords.w, true, true) + TaskWarpPedIntoVehicle(PlayerPedId(), vehicle, -1) + Interact = false + end) + + lib.showMenu(menu_id) +end + +function OpenNPCMenu(index) + local menu_id = "airport_npc_menu" + local options = {} + for i=1, #Config.Airports do + if index ~= i then + local _index = i + options[#options + 1] = {label = Config.Airports[i].AirportTitle, description = "", index = _index} + end + end + lib.registerMenu({ + id = menu_id, + title = 'Choose Destination', + position = 'top-left', + onClose = function(keyPressed) + Interact = false + end, + options = options + }, function(selected, scrollIndex, args) + StartNPCFlight(options[selected].index) + end) + lib.showMenu(menu_id) +end + +function InteractAirport(index, key) + Interact = true + if (key == "Boarding") then + local data = GlobalState.Flights[index] + if (data) then + JoinActiveFlight(index) + elseif (Config.AirportSettings.NPCFlightCost) then + OpenNPCMenu(index) + else + ShowHelpNotification(U.Boarding_unavailable) + end + elseif (key == "Flight") then + if not PermissionCheck("flight") then + Interact = false + ShowNotification(U.Flight_denied) + return + end + local vehicle = GetCurrentAircraft() + if vehicle then + local seats = GetVehicleModelNumberOfSeats(GetEntityModel(vehicle)) - 2 + local players = {} + local found = false + for i=1, seats do + if not IsVehicleSeatFree(vehicle, i) then + local player = NetworkGetPlayerIndexFromPed(GetPedInVehicleSeat(vehicle, i)) + if (player) then + found = true + players[#players + 1] = GetPlayerServerId(player) + end + end + end + if found then + TriggerServerEvent("pickle_airport:returnPassengers", index, players) + Interact = false + else + OpenFlightMenu(index, vehicle) + end + else + Interact = false + --ShowNotification("You are not able to start a flight without being in a plane.") + end + elseif (key == "Hangar") then + if not PermissionCheck("hangar") then + Interact = false + ShowNotification(U.Hangar_denied) + return + end + local vehicle = GetCurrentAircraft() + if vehicle then + DeleteEntity(vehicle) + Interact = false + else + OpenSpawnMenu(index) + end + end +end + +function ShowInteract(index, key) + local airport = Config.Airports[index] + local ped = PlayerPedId() + local pcoords = GetEntityCoords(ped) + local coords, heading = v3(airport.Locations[key]) + local dist = #(coords - pcoords) + if not Interact and dist < 20.0 then + if (dist < 1.75) then + if (key == "Boarding") then + local data = GlobalState.Flights[index] + if (data) then + local airport = Config.Airports[index] + local dest = Config.Airports[data.destination] + ShowHelpNotification("~INPUT_CONTEXT~ " .. airport.AirportTitle .. " -> " .. dest.AirportTitle .. " ($" .. data.price .. ")") + elseif (Config.AirportSettings.NPCFlightCost) then + ShowHelpNotification(U.Boarding_npc_interact .. Config.AirportSettings.NPCFlightCost .. ".") + else + ShowHelpNotification(U.Boarding_unavailable) + end + return true, true + elseif (key == "Flight") then + local vehicle = GetCurrentAircraft() + if vehicle then + local seats = GetVehicleModelNumberOfSeats(GetEntityModel(vehicle)) - 2 + local found = false + for i=1, seats do + if not IsVehicleSeatFree(vehicle, i) then + found = true + break + end + end + if found then + ShowHelpNotification(U.Flight_return) + else + ShowHelpNotification(U.Flight_interact) + end + return true, true + else + ShowHelpNotification(U.Flight_reject) + return false, true + end + elseif (key == "Hangar") then + local vehicle = GetCurrentAircraft() + if vehicle then + ShowHelpNotification(U.Hangar_return) + else + ShowHelpNotification(U.Hangar_interact) + end + return true, true + end + else + if (key == "Boarding") then + return nil, true + elseif (key == "Flight") then + return nil, true + elseif (key == "Hangar") then + return nil, true + end + end + end +end + +RegisterNetEvent("pickle_airport:returnBoarding", function(index) + local cfg = Config.Airports[index] + local coords = cfg.Locations.Flight + local ped = PlayerPedId() + if #(coords - GetEntityCoords(ped)) < 10.0 then + local coords = cfg.Locations.Boarding + DoScreenFadeOut(1000) + Wait(1500) + SetEntityCoords(ped, coords.x, coords.y, coords.z) + Wait(100) + DoScreenFadeIn(1000) + end +end) + +CreateThread(function() + for i=1, #Config.Airports do + local airport = Config.Airports[i] + if airport.Blips then + for k,v in pairs(airport.Blips) do + local data = v + data.Location = v3(airport.Locations[k]) + CreateBlip(data) + end + end + end + while true do + local wait = 1000 + for i=1, #Config.Airports do + local airport = Config.Airports[i] + for k,v in pairs(airport.Locations) do + local inZone, displayZone = ShowInteract(i, k) + if (displayZone) then + wait = 0 + local coords, heading = v3(v) + DrawMarker(2, coords.x, coords.y, coords.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.25, 0.25, 0.25, 255, 255, 255, 127, false, true) + if (inZone and IsControlJustPressed(1, 51)) then + InteractAirport(i, k) + end + end + end + end + Wait(wait) + end +end) \ No newline at end of file diff --git a/modules/airports/server.lua b/modules/airports/server.lua new file mode 100644 index 0000000..53f07c9 --- /dev/null +++ b/modules/airports/server.lua @@ -0,0 +1,59 @@ +local Flights = {} +GlobalState.Flights = Flights + +function UpdateFlights() + GlobalState.Flights = Flights +end + +RegisterCallback("pickle_airport:startFlight", function(source, cb, index, flight_info) + if (Flights[index]) then + cb(false) + return + else + if PermissionCheck(source, "flight") then + Flights[index] = flight_info + Flights[index].source = source + UpdateFlights() + cb(Flights[index]) + SetTimeout(1000 * Config.AirportSettings.DepartureTime, function() + Flights[index] = nil + UpdateFlights() + end) + else + cb(false) + return + end + end +end) + +RegisterCallback("pickle_airport:startNPCFlight", function(source, cb, index) + if (Config.AirportSettings.NPCFlightCost and Search(source, "money") - Config.AirportSettings.NPCFlightCost >= 0) then + RemoveItem(source, "money", Config.AirportSettings.NPCFlightCost) + cb(true) + return + else + cb(false) + return + end +end) + +RegisterCallback("pickle_airport:purchaseTicket", function(source, cb, index) + if (Flights[index] and Search(source, "money") - Flights[index].price >= 0) then + RemoveItem(source, "money", Flights[index].price) + cb(true) + return + else + cb(false) + return + end +end) + + +RegisterNetEvent("pickle_airport:returnPassengers", function(index, passengers) + local source = source + if PermissionCheck(source, "flight") then + for i=1, #passengers do + TriggerClientEvent("pickle_airport:returnBoarding", passengers[i], index) + end + end +end) \ No newline at end of file diff --git a/modules/missions/client.lua b/modules/missions/client.lua new file mode 100644 index 0000000..c6992d8 --- /dev/null +++ b/modules/missions/client.lua @@ -0,0 +1,278 @@ +local MissionIndex, MissionAircraft, MissionBlip = nil, nil, nil + +function SetMissionBlip(coords, blipType) + if MissionBlip ~= nil then + RemoveBlip(MissionBlip) + MissionBlip = nil + end + if coords then + local info = Config.Missions.Blips[blipType] + MissionBlip = CreateBlip({ + Location = coords, + Label = info.Label, + ID = info.ID, + Scale = info.Scale, + Color = info.Color + }) + end +end + +function DeliveryMission(index, cb) + local mission = Config.Missions.Sequences[index] + local boxProp = nil + + local function Cleanup() + SetMissionBlip() + + if boxProp then + local ped = PlayerPedId() + DeleteEntity(boxProp) + ClearPedSecondaryTask(ped) + boxProp = nil + end + end + + Citizen.CreateThread(function() + local done = false + + ShowNotification(U.package_pickup_notify) + SetMissionBlip(mission.PackagePickup, "PackagePickup") + + while index == MissionIndex and not done do + if (not DoesEntityExist(MissionAircraft) or GetEntityHealth(MissionAircraft) <= 0) then + Cleanup() + cb(false) + return + end + local wait = 1000 + local ped = PlayerPedId() + local coords = mission.PackagePickup + local pcoords = GetEntityCoords(ped) + local dist = #(coords - pcoords) + if (dist < 20) then + wait = 0 + DrawMarker(2, coords.x, coords.y, coords.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.25, 0.25, 0.25, 255, 255, 255, 127, false, true) + if (dist < 1.25 and not ShowHelpNotification(U.package_pickup) and IsControlJustPressed(1, 51)) then + done = true + break + end + end + Wait(wait) + end + + if (not done) then + Cleanup() + cb(false) + return + end + done = false + + ShowNotification(U.package_dropoff_notify) + SetMissionBlip(mission.PackageDropoff, "PackageDropoff") + + while index == MissionIndex and not done do + if (not DoesEntityExist(MissionAircraft) or GetEntityHealth(MissionAircraft) <= 0) then + Cleanup() + cb(false) + return + end + + local wait = 1000 + local ped = PlayerPedId() + local coords = mission.PackageDropoff + local pcoords = GetEntityCoords(ped) + local acoords = GetEntityCoords(MissionAircraft) + local dist = #(coords - pcoords) + local adist = #(coords - acoords) + local vehicle = GetVehiclePedIsIn(ped) + if (vehicle ~= 0 and boxProp) then + DeleteEntity(boxProp) + ClearPedSecondaryTask(ped) + boxProp = nil + elseif (vehicle == 0) then + if not IsEntityPlayingAnim(ped, "anim@heists@box_carry@", "idle", 13) then + PlayAnim(ped, "anim@heists@box_carry@", "idle", -8.0, 8.0, -1, 49, 1.0) + Wait(10) + end + if (not boxProp) then + local bone = GetPedBoneIndex(ped, 60309) + local c, r = vec3(0.025, 0.08, 0.285), vec3(-165.0, 250.0, 0.0) + boxProp = CreateProp(`hei_prop_heist_box`, pcoords.x, pcoords.y, pcoords.z, true, true) + AttachEntityToEntity(boxProp, ped, bone, c.x, c.y, c.z, r.x, r.y, r.z, false, false, false, false, 2, true) + elseif (boxProp and dist < 20 and adist < 40) then + wait = 0 + DrawMarker(2, coords.x, coords.y, coords.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.25, 0.25, 0.25, 255, 255, 255, 127, false, true) + if (dist < 1.25 and not ShowHelpNotification(U.package_dropoff) and IsControlJustPressed(1, 51)) then + done = true + break + end + end + end + Wait(wait) + end + + Cleanup() + + cb(done) + end) +end + +function PassengerMission(index, cb) + local mission = Config.Missions.Sequences[index] + local peds = {} + local seats = GetVehicleModelNumberOfSeats(GetEntityModel(MissionAircraft)) - 2 + + local function Cleanup() + SetMissionBlip() + for i=1, #peds do + DeleteEntity(peds[i]) + end + end + Citizen.CreateThread(function() + local done = false + + ShowNotification(U.passenger_pickup_notify) + SetMissionBlip(mission.PassengerPickup, "PassengerPickup") + + while index == MissionIndex and not done do + if (not DoesEntityExist(MissionAircraft) or GetEntityHealth(MissionAircraft) <= 0) then + Cleanup() + cb(false) + return + end + local wait = 1000 + local ped = PlayerPedId() + local coords = mission.PassengerPickup + local pcoords = GetEntityCoords(ped) + local dist = #(coords - pcoords) + if (dist < 20) then + wait = 0 + DrawMarker(2, coords.x, coords.y, coords.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.75, 0.75, 0.75, 255, 255, 255, 127, false, true) + if (dist < 1.25 and not ShowHelpNotification(U.passenger_pickup) and IsControlJustPressed(1, 51)) then + done = true + break + end + end + Wait(wait) + end + + if (done) then + ShowNotification(U.passenger_loading) + FreezeEntityPosition(MissionAircraft, true) + local vehicle = MissionAircraft + local coords = mission.PassengerPickup + for i=1, seats do + if IsVehicleSeatFree(vehicle, i) then + local ped = CreateNPC(`g_m_m_armboss_01`, coords.x, coords.y, coords.z + 100.0, 0.0, true, true) + peds[#peds + 1] = ped + TaskWarpPedIntoVehicle(ped, vehicle, i) + Wait(1000) + end + end + FreezeEntityPosition(MissionAircraft, false) + else + Cleanup() + cb(false) + return + end + + done = false + + ShowNotification(U.passenger_dropoff_notify) + SetMissionBlip(mission.PassengerDropoff, "PassengerDropoff") + + while index == MissionIndex and not done do + if (not DoesEntityExist(MissionAircraft) or GetEntityHealth(MissionAircraft) <= 0) then + Cleanup() + cb(false) + return + end + + local wait = 1000 + local ped = PlayerPedId() + local coords = mission.PassengerDropoff + local pcoords = GetEntityCoords(ped) + local acoords = GetEntityCoords(MissionAircraft) + local dist = #(coords - pcoords) + local adist = #(coords - acoords) + local vehicle = GetVehiclePedIsIn(ped) + if (vehicle == MissionAircraft and dist < 20 and adist < 40) then + wait = 0 + DrawMarker(2, coords.x, coords.y, coords.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.75, 0.75, 0.75, 255, 255, 255, 127, false, true) + if (dist < 1.25 and not ShowHelpNotification(U.passenger_dropoff) and IsControlJustPressed(1, 51)) then + done = true + break + end + end + Wait(wait) + end + + if (done) then + ShowNotification(U.passenger_unloading) + FreezeEntityPosition(MissionAircraft, true) + local vehicle = MissionAircraft + for i=1, #peds do + DeleteEntity(peds[i]) + Wait(1000) + end + FreezeEntityPosition(MissionAircraft, false) + Cleanup() + else + Cleanup() + cb(false) + return + end + + + cb(done) + end) +end + +function StopMission() + MissionIndex = nil + MissionAircraft = nil + SetMissionBlip() +end + +function StartMission(lastIndex, vehicle) + local vehicle = vehicle or GetCurrentAircraft() + if not vehicle then + ShowNotification("You cannot start a mission without being in a aircraft.") + elseif MissionIndex == nil then + local index = GetRandomInt(1, #Config.Missions.Sequences, lastIndex) + MissionIndex = index + MissionAircraft = vehicle + local mission = Config.Missions.Sequences[MissionIndex] + if (mission.Type == "Delivery") then + DeliveryMission(MissionIndex, function(result) + if result then + ShowNotification("Mission completed!") + TriggerServerEvent("pickle_airport:finishedMission", MissionIndex) + else + ShowNotification("Mission failed.") + end + StopMission() + end) + elseif (mission.Type == "Passenger") then + PassengerMission(MissionIndex, function(result) + if result then + ShowNotification("Mission completed!") + TriggerServerEvent("pickle_airport:finishedMission", MissionIndex) + else + ShowNotification("Mission failed.") + end + StopMission() + end) + end + else + StopMission() + end +end + +RegisterCommand("pilotmission", function() + if (PermissionCheck("pilot_mission")) then + StartMission() + else + ShowNotification(U.permission_denied) + end +end) \ No newline at end of file diff --git a/modules/missions/server.lua b/modules/missions/server.lua new file mode 100644 index 0000000..9aef23e --- /dev/null +++ b/modules/missions/server.lua @@ -0,0 +1,13 @@ +RegisterNetEvent("pickle_airport:finishedMission", function(index) + local source = source + if (PermissionCheck(source, "pilot_mission")) then + local data = Config.Missions.Sequences[index] + local rewards = data.Rewards + for i=1, #rewards do + local amount = GetRandomInt(rewards[i].min, rewards[i].max) + AddItem(source, rewards[i].name, amount) + end + else + ShowNotification(source, U.permission_denied) + end +end) \ No newline at end of file diff --git a/modules/tracker/client.lua b/modules/tracker/client.lua new file mode 100644 index 0000000..227d224 --- /dev/null +++ b/modules/tracker/client.lua @@ -0,0 +1,56 @@ +TrackedAircraft = {} + +function GetCurrentAircraft() + local ped = PlayerPedId() + local vehicle = GetVehiclePedIsIn(ped, false) + if (vehicle and GetPedInVehicleSeat(vehicle, -1) == ped) then + if (IsPedInAnyPlane(ped)) then + return vehicle, 1 + elseif (IsPedInAnyHeli(ped)) then + return vehicle, 2 + end + end +end + +function UpdateClientTracker(source, data) + if (TrackedAircraft[source] and TrackedAircraft[source].blip) then + RemoveBlip(TrackedAircraft[source].blip) + end + if (data) then + TrackedAircraft[source] = data + + local info = Config.Tracker.BlipTypes[data.aircraftType] + + if (PermissionCheck("view_tracker")) then + TrackedAircraft[source].blip = CreateBlip({ + Location = data.coords, + Rotation = data.heading, + Label = info.Label, + ID = info.ID, + Scale = info.Scale, + Color = info.Color + }) + end + else + TrackedAircraft[source] = nil + end +end + +CreateThread(function() + while true do + local wait = 1000 * Config.Tracker.UpdateTime + local vehicle, aircraftType = GetCurrentAircraft() + if vehicle then + local coords = GetEntityCoords(vehicle) + local heading = GetEntityHeading(vehicle) + TriggerServerEvent("pickle_airport:tracker:updateAircraft", {coords = coords, heading = heading, aircraftType = aircraftType}) + elseif TrackedAircraft[GetPlayerServerId(PlayerId())] then + TriggerServerEvent("pickle_airport:tracker:updateAircraft", nil) + end + Wait(wait) + end +end) + +RegisterNetEvent("pickle_airport:tracker:receiveAircraftUpdate", function(source, data) + UpdateClientTracker(source, data) +end) \ No newline at end of file diff --git a/modules/tracker/server.lua b/modules/tracker/server.lua new file mode 100644 index 0000000..8b6d8e1 --- /dev/null +++ b/modules/tracker/server.lua @@ -0,0 +1,15 @@ +TrackedAircraft = {} + +function UpdateTracker(source, data) + if (data) then + TrackedAircraft[source] = data + else + TrackedAircraft[source] = nil + end + TriggerClientEvent("pickle_airport:tracker:receiveAircraftUpdate", -1, source, TrackedAircraft[source]) +end + +RegisterNetEvent("pickle_airport:tracker:updateAircraft", function(data) + local source = source + UpdateTracker(source, data) +end) \ No newline at end of file