5Mdev
← Resources
FreeGitHubTrusted resource

QBcore Airdrop Resource

New0 reviews

A complete airdrop system for QBcore framework using ox_lib UI. Players can request airdrops at designated locations with configurable items and cooldown periods.

Resource Specifications

  • Framework: QBCORE
  • UI Standard: ox_lib
  • Language: LUA

Included Files (4)

fxmanifest.lua

lua
fx_version 'cerulean'
game 'gta5'
lua54 'yes'

name 'qb_airdrop'
description 'Airdrop system for QBcore framework'
version '1.0.0'
author 'FiveM Developer'

shared_script '@ox_lib/init.lua'

client_scripts {
    'client/main.lua',
    'config.lua'
}

server_scripts {
    '@oxmysql/lib/MySQL.lua',
    'server/main.lua',
    'config.lua'
}

files {
    'html/index.html',
    'html/style.css',
    'html/script.js'
}

ui_page 'html/index.html'

export 'TriggerAirdrop'

config.lua

lua
Config = {}

Config.AirdropSettings = {
    CooldownTime = 300,
    MaxItemsPerDrop = 5,
    DropHeight = 100.0,
    DropRadius = 50.0,
    LandingEffect = true,
    SoundEnabled = true,
    NotificationType = "advanced"
}

Config.AirdropLocations = {
    { x = 123.45, y = 678.90, z = 123.45 },
    { x = -234.56, y = 789.01, z = 123.45 },
    { x = 345.67, y = -890.12, z = 123.45 }
}

Config.AirdropItems = {
    { item = "weapon_pistol", amount = 1, chance = 10 },
    { item = "ammo_pistol", amount = 50, chance = 20 },
    { item = "bread", amount = 2, chance = 30 },
    { item = "water_bottle", amount = 2, chance = 30 },
    { item = "bandage", amount = 3, chance = 25 },
    { item = "radio", amount = 1, chance = 15 },
    { item = "repairkit", amount = 1, chance = 10 }
}

Config.AirdropVehicles = {
    "tug",
    "cargoplane",
    "luxor",
    "maverick"
}

Config.Sounds = {
    StartSound = "airdrop_start",
    DropSound = "airdrop_drop",
    LandingSound = "airdrop_landing"
}

Config.Messages = {
    RequestSuccess = "Airdrop requested successfully! Get ready for landing.",
    RequestCooldown = "You must wait %s before requesting another airdrop.",
    NoLocation = "No available airdrop location found.",
    ItemReceived = "You received %s x%s from the airdrop!",
    NotEnoughMoney = "You don't have enough money for an airdrop.",
    InvalidLocation = "Invalid airdrop location selected."
}

client/main.lua

lua
local QBCore = exports["qb-core"]:GetCoreObject()
local PlayerData = QBCore.Functions.GetPlayerData()
local currentCooldown = 0
local isAirdropping = false

AddEventHandler("onResourceStart", function(resourceName)
    if resourceName == GetCurrentResourceName() then
        print("[AIRDROP] Airdrop system initialized")
    end
end)

RegisterCommand("airdrop", function(source, args, rawCommand)
    if not IsPedInAnyVehicle(PlayerPedId(), false) then
        OpenAirdropMenu()
    else
        QBCore.Functions.Notify("You cannot request an airdrop while in a vehicle!", "error")
    end
end, false)

function OpenAirdropMenu()
    if currentCooldown > 0 then
        local timeLeft = math.ceil(currentCooldown / 60)
        QBCore.Functions.Notify(string.format(Config.Messages.RequestCooldown, timeLeft .. " minute(s)"), "error")
        return
    end

    local locations = {}
    for i, loc in ipairs(Config.AirdropLocations) do
        table.insert(locations, {
            title = "Location " .. i,
            description = "Request airdrop here",
            value = i
        })
    end

    local options = {
        {
            title = "Request Airdrop",
            description = "Request a supply drop at a location",
            icon = "plane",
            onSelect = function()
                if #locations > 0 then
                    ox_lib.menu("airdrop_locations", locations)
                else
                    QBCore.Functions.Notify(Config.Messages.NoLocation, "error")
                end
            end
        },
        {
            title = "Check Cooldown",
            description = "See how long until you can request again",
            icon = "clock",
            onSelect = function()
                if currentCooldown > 0 then
                    local timeLeft = math.ceil(currentCooldown / 60)
                    QBCore.Functions.Notify("Cooldown: " .. timeLeft .. " minute(s)", "info")
                else
                    QBCore.Functions.Notify("No cooldown active", "success")
                end
            end
        }
    }

    ox_lib.menu("airdrop_menu", options)
end

AddEventHandler("ox_lib:menuSelected", function(menu, option)
    if menu == "airdrop_locations" then
        local locationIndex = option.value
        if locationIndex and locationIndex >= 1 and locationIndex <= #Config.AirdropLocations then
            TriggerServerEvent("qb_airdrop:requestAirdrop", locationIndex)
        else
            QBCore.Functions.Notify(Config.Messages.InvalidLocation, "error")
        end
    elseif menu == "airdrop_menu" then

    end
end)

RegisterNetEvent("qb_airdrop:response", function(success, message)
    if success then
        QBCore.Functions.Notify(message, "success")
    else
        QBCore.Functions.Notify(message, "error")
    end
end)

RegisterNetEvent("qb_airdrop:updateCooldown", function(seconds)
    currentCooldown = seconds
    if seconds > 0 then

        CreateThread(function()
            while currentCooldown > 0 do
                Wait(1000)
                currentCooldown = currentCooldown - 1
            end
        end)
    end
end)

RegisterNetEvent("qb_airdrop:startAirdrop", function(locationIndex)
    if isAirdropping then return end
    isAirdropping = true
    
    local location = Config.AirdropLocations[locationIndex]
    if not location then
        QBCore.Functions.Notify(Config.Messages.InvalidLocation, "error")
        isAirdropping = false
        return
    end

    if Config.AirdropSettings.LandingEffect then
        DrawLightWithRange(location.x, location.y, location.z + 10, 255, 255, 255, 100, 100)
    end

    if Config.AirdropSettings.SoundEnabled then
        PlaySoundFrontend(-1, Config.Sounds.StartSound, "DLC_APT_AIRPORT_SOUNDSET", true)
    end

    local dropPosition = vector3(location.x, location.y, location.z + Config.AirdropSettings.DropHeight)
    local groundZ = GetGroundZFor_3dCoord(location.x, location.y, location.z + 100)

    local plane = CreateVehicle("cargoplane", dropPosition.x, dropPosition.y, dropPosition.z, 0.0, true, false)
    SetEntityHeading(plane, 0.0)
    SetEntityVisible(plane, false)

    TaskPlaneMission(plane, PlayerPedId(), 0, 0, dropPosition.x, dropPosition.y, dropPosition.z, 0, 0, 0, 0, 0)

    Wait(5000)

    local dropEffect = CreateParticleFxAssetNextCall("scr_airdrop")

    local items = GenerateRandomItems()
    for i, item in ipairs(items) do
        local dropPos = vector3(location.x + math.random(-Config.AirdropSettings.DropRadius, Config.AirdropSettings.DropRadius),
                              location.y + math.random(-Config.AirdropSettings.DropRadius, Config.AirdropSettings.DropRadius),
                              groundZ)

        local pickup = CreateObject("prop_weed_01", dropPos.x, dropPos.y, dropPos.z, true, true, false)
        SetEntityHeading(pickup, math.random(0, 360))

        table.insert(airdropPickups, pickup)
    end

    DeleteEntity(plane)

    QBCore.Functions.Notify("Airdrop has landed! Check around the area.", "success")
    isAirdropping = false
end)

function GenerateRandomItems()
    local items = {}
    local itemCount = math.random(1, Config.AirdropSettings.MaxItemsPerDrop)
    
    for i = 1, itemCount do
        local totalChance = 0
        for _, item in ipairs(Config.AirdropItems) do
            totalChance = totalChance + item.chance
        end
        
        local randomValue = math.random(1, totalChance)
        local cumulativeChance = 0
        
        for _, item in ipairs(Config.AirdropItems) do
            cumulativeChance = cumulativeChance + item.chance
            if randomValue <= cumulativeChance then
                table.insert(items, {
                    item = item.item,
                    amount = item.amount
                })
                break
            end
        end
    end
    
    return items
end

CreateThread(function()
    while true do
        Wait(100)
        local playerPed = PlayerPedId()
        local playerCoords = GetEntityCoords(playerPed)
        
        for i, pickup in ipairs(airdropPickups or {}) do
            local pickupCoords = GetEntityCoords(pickup)
            local distance = #(playerCoords - pickupCoords)
            
            if distance < 2.0 then

                DrawText3D(pickupCoords.x, pickupCoords.y, pickupCoords.z + 1.0, "Press ~INPUT_CONTEXT~ to collect")
                
                if IsControlJustPressed(0, 51) then

                    TriggerServerEvent("qb_airdrop:collectItem", i)
                    DeleteEntity(pickup)
                    table.remove(airdropPickups, i)
                end
            end
        end
    end
end)

function DrawText3D(x, y, z, text)
    SetDrawOrigin(x, y, z, 0)
    SetTextFont(4)
    SetTextProportional(1)
    SetTextScale(0.0, 0.20)
    SetTextColour(255, 255, 255, 255)
    SetTextDropshadow(0, 0, 0, 0, 255)
    SetTextEdge(1, 0, 0, 0, 255)
    SetTextDropShadow()
    SetTextOutline()
    SetTextEntry("STRING")
    AddTextComponentString(text)
    DrawText(0.0, 0.0)
    ClearDrawOrigin()
end

function TriggerAirdrop(locationIndex)
    if not IsPedInAnyVehicle(PlayerPedId(), false) then
        TriggerServerEvent("qb_airdrop:requestAirdrop", locationIndex)
    else
        QBCore.Functions.Notify("You cannot request an airdrop while in a vehicle!", "error")
    end
end

airdropPickups = {}

server/main.lua

lua
local QBCore = exports["qb-core"]:GetCoreObject()
local MySQL = require "lib/MySQL"

AddEventHandler("onResourceStart", function(resourceName)
    if resourceName == GetCurrentResourceName() then
        print("[AIRDROP] Airdrop system initialized on server")
    end
end)

RegisterNetEvent("qb_airdrop:requestAirdrop")
AddEventHandler("qb_airdrop:requestAirdrop", function(locationIndex)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    
    if not Player then return end

    local cooldown = GetPlayerCooldown(src)
    if cooldown > 0 then
        TriggerClientEvent("qb_airdrop:response", src, false, string.format(Config.Messages.RequestCooldown, math.ceil(cooldown / 60) .. " minute(s)"))
        return
    end

    if not Config.AirdropLocations[locationIndex] then
        TriggerClientEvent("qb_airdrop:response", src, false, Config.Messages.InvalidLocation)
        return
    end

    SetPlayerCooldown(src, Config.AirdropSettings.CooldownTime)

    TriggerClientEvent("qb_airdrop:response", src, true, Config.Messages.RequestSuccess)

    TriggerClientEvent("qb_airdrop:startAirdrop", src, locationIndex)

    TriggerClientEvent("qb_airdrop:notification", -1, "A new airdrop has been requested!")
end)

RegisterNetEvent("qb_airdrop:collectItem")
AddEventHandler("qb_airdrop:collectItem", function(itemIndex)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    
    if not Player then return end

    local items = GenerateRandomItems()
    
    for _, item in ipairs(items) do
        if Player.Functions.AddItem(item.item, item.amount) then
            TriggerClientEvent("qb_airdrop:response", src, true, string.format(Config.Messages.ItemReceived, item.amount, item.item))
        else
            TriggerClientEvent("qb_airdrop:response", src, false, "Failed to add item to inventory")
        end
    end
end)

function GetPlayerCooldown(playerId)
    local result = MySQL.scalar.await("SELECT cooldown FROM players WHERE citizenid = ?", {QBCore.Functions.GetPlayer(playerId).PlayerData.citizenid})
    if result then
        return result
    else
        return 0
    end
end

function SetPlayerCooldown(playerId, seconds)
    local player = QBCore.Functions.GetPlayer(playerId)
    if player then
        MySQL.query("UPDATE players SET cooldown = ? WHERE citizenid = ?", {seconds, player.PlayerData.citizenid})
        TriggerClientEvent("qb_airdrop:updateCooldown", playerId, seconds)
    end
end

function GenerateRandomItems()
    local items = {}
    local itemCount = math.random(1, Config.AirdropSettings.MaxItemsPerDrop)
    
    for i = 1, itemCount do
        local totalChance = 0
        for _, item in ipairs(Config.AirdropItems) do
            totalChance = totalChance + item.chance
        end
        
        local randomValue = math.random(1, totalChance)
        local cumulativeChance = 0
        
        for _, item in ipairs(Config.AirdropItems) do
            cumulativeChance = cumulativeChance + item.chance
            if randomValue <= cumulativeChance then
                table.insert(items, {
                    item = item.item,
                    amount = item.amount
                })
                break
            end
        end
    end
    
    return items
end

AddEventHandler("onResourceStop", function(resourceName)
    if resourceName == GetCurrentResourceName() then
        print("[AIRDROP] Airdrop system stopped")
    end
end)
QBcore Airdrop Resource | 5Mdev