Open files preview
Config & Utils files preview, these files are ignored by the escrow system and can be modified.
This script is highly customizable, there is a total of 4 files accessible for you.
config/config.lua
Click here to see a preview config.lua
Config = {}
-- _____ _____ _
-- | __ \ (_) / ____| | |
-- | |__) |__ _ ___ ___ _ __ | | ___ __| | ___
-- | ___/ _ \| / __|/ _ \| '_ \| | / _ \ / _` |/ _ \
-- | | | (_) | \__ \ (_) | | | | |___| (_) | (_| | __/
-- |_| \___/|_|___/\___/|_| |_|\_____\___/ \__,_|\___|
-- © PoisonCode
-- Discord: https://discord.gg/rNJ8cHXCsN
-- Tebex: https://poisoncode.tebex.io
----- This script is highly customizable, plase take your time and adjust it to your needs! ------
--------------------------------------------------------------------------------------------------
-- --------------- If you encounter any bugs, please report it on our discord ---------------- --
-- Documentation available at: https://poisoncode.gitbook.io/poisoncode-docs/scripts/pc_airdrop --
--------------------------------------------------------------------------------------------------
-- BY DEFAULT REWARD ITEMS ARE GIVEN USING ESX OR QBCORE FUNCTION.
-- SEE utils/server.lua TO MODIFY FUNCTION RESPONSIBLE FOR ADDING ITEMS TO INVENTORY!
Config.UseExperimentalFeatures = false -- If you want to use experimental features, set this to true. (Experimental features are not fully tested and may not work as expected)
Config.ClientDebugMessages = false -- Enables additional debug messages on the client side console (F8), we recommend turning this off while not debugging
Config.ServerDebugMessages = true -- Enables additional debug messages on the server side console, you can keep it on if these messages don't bother you
-- ^^ (Errors and warnings will always be displayed) ^^
-- Technical --
Config.Framework = "NEW-ESX" -- "NEW-ESX" - "ESX" - "QBCore"
Config.UseCollision2 = false -- If you're experiencing an error where the airdrop gets stuck in the air, set this to true, otherwise it's not recommended
-- Basic --
Config.CaptureTime = 15 -- Time (in seconds) required to capture an airdrop
Config.CaptureDistance = 10 -- How far can you go before airdrop capture is canceled
Config.AirdropFallSpeed = 1 -- How quick should the airdrop fall. Default 1 (Slowest setting) (Used only when Config.AirdropGroundSpawn is false)
Config.AirdropGroundSpawn = false -- Should the airdrop spawn directly on the ground (Without falling down from the sky)
Config.LocationNotification = true -- If set to true, notification will contain airdrop name and location name
-- Discord logs --
Config.DiscordLogs = false -- Set to true if you want to recieve discord logs. (set your webhook in server utils)
-- Integrations --
Config.Use_Target = false -- If you set this option to true, collecting the airdrop will be possible only using qTarget or ox_target
Config.Target = "ox_target" -- "qtarget" or "ox_target" or "qb-target"
Config.Use_OxInventory = false -- Turns on ox_inventory integration
Config.RemoveWhenEmpty = false -- When using ox_inventory, should the airdrop crate be removed when players take all the items
Config.Use_pcnotifications = GetResourceState('pc_notifications') == 'started' or false -- Automatically turns the pc_notification on or off
-- Advanced --
Config.Plane = {
enable = true, -- Should there be a plane flying by and dropping the airdrop
distance = 500, -- How far should the plane spawn (bigger value = longer fly time)
speed = 50, -- How fast should the plane travel
}
Config.AirdropRemove = {
enable = true, -- Removes the airdrop after a period of time. Especially recommended if you're using ox_inventory integration
time = 1200, -- Time (in seconds) after the airdrop is automatically removed from the map (example 1200 sec = 20 min)
}
Config.AirdropLock = {
enable = true, -- After falling/spawning, should the airdrop be locked
showtext = true, -- Should there be 3D/Helpnotification/custom text showed when the airdrop is locked AirdropLock.enable should be set to true
time = 15, -- How long should the airdrop be locked for after falling/spawning
}
Config.Models = {
-- You can change crate and/or parachute prop model. List of all props: https://gta-objects.xyz/objects/
-- Warning: some models might not work or have different physics. Change at your own risk
crate = "xm_prop_rsply_crate04a",
parachute = "p_parachute1_mp_dec",
-- Plane model
plane = "titan",
-- Ped model for pilot. List of all peds: https://docs.fivem.net/docs/game-references/ped-models/
npc_pilot = "s_m_m_pilot_02",
}
Config.ShowFlares = {
[1] = true, -- Should there be a "flare effect" on the ground when the airdrop is falling ? (true/false)
[2] = true, -- Should there be a "flare + smoke effect" on the airdrop crate when it lands on the ground ? (true/false)
}
-- Basic methods of spawning an airdrop
Config.AirdropSpawnMethod = {
event_enabled = false, -- Creates a custom server event for calling an airdrop (customize in utils/server.lua)
command_enabled = true, -- Should you be able to call command /airdrop (customize in utils/server.lua) WARNING: BY DEFAULT COMMAND IS AVAILABLE FOR EVERYONE
auto_enabled = false, -- Should there be an airdrop every X minutes (Set cooldown below)
auto_delay = 10, -- After server/script restart, first airdrop will be called in after this delay (in minutes) DEFAULT: 10 MINUTE DELAY
auto_timer = 60, -- Time in minutes between airdrops. DEFAULT: AIRDROP EVERY 60 MINUTES
}
-- If you want your airdrop to be called in a random spot within provided coords and radius set Config.AirDropInRadius to true.
-- If you set Config.AirDropInRadius to false, the airdrop will always land on provided coords, and radius will be ignored (we suggest to disable radius blip if in that case).
-- Airdrop location will be choosen at random from coords provided below, unless a forced location will be provided with a command or through event.
-- Bear in mind that this script does not check if location is safe, it is possible that the airdrop falls in water. Be cautious when setting spawn radius
Config.AirDropInRadius = true
Config.Locations = {
{label = "Location1", coords = vector3(3678.45, 4983.75, 15.83), radius = 50},
{label = "Location2", coords = vector3(1450.03, 4408.11, 46.77), radius = 50},
{label = "Location3", coords = vector3(112.3445, 6827.7622, 17.0759), radius = 80},
{label = "Location4", coords = vector3(2504.6265, 3264.5303, 52.1214), radius = 50},
{label = "Location5", coords = vector3(1573.6575, 3196.3611, 40.5308), radius = 70},
{label = "Location6", coords = vector3(334.0565, 2849.8423, 43.4093), radius = 60},
{label = "Location7", coords = vector3(-2171.0454, 3063.4260, 32.9654), radius = 60},
{label = "Location8", coords = vector3(-1334.5094, -3040.9614, 13.9444), radius = 100},
{label = "Location9", coords = vector3(1373.5991, -745.4987, 67.2328), radius = 60},
}
-- Configure airdrops and their loot, type of spawned airdrop is random.
-- ItemName is the name used to give the item to the player.
-- ItemAmount OR ItemAmountMin & ItemAmountMax is the amount of this item that should be awarded to player.
-- If using ItemAmountMin & ItemAmountMax the amount will be chosen at random between these two values
-- Chance is the chance (1-100) that the player recieves this item. If set to 100, player will always recieve this reward.
-- Type "item" or "weapon" (will be ignored if using ox_inventory), used when you DONT use "weapons as items" (you can only have one weapon of given type for example).
Config.AirDrops = {
[1] = { -- Airdrop id number (has to bee different for each airdrop)
['name'] = "Medical", -- Name of the airdrop that will be shown in notifications
['items'] = { -- Loot table
{ItemName = "bandage", ItemAmountMin = 5, ItemAmountMax = 10, Chance = 100, Type = "item"}, -- items, amount and chance
{ItemName = "medikit", ItemAmount = 1, Chance = 90, Type = "item"},
},
},
[2] = {
['name'] = "Weapons", -- Name of the airdrop that will be shown in notifications
['items'] = { -- Loot table
{ItemName = "weapon_pistol", ItemAmount = 1, Chance = 100, Type = "item"}, -- <- if not using ox_inventory or other "weapons as items" script, change type to "weapon"
{ItemName = "weapon_pistol50", ItemAmount = 1, Chance = 10, Type = "item"},
},
},
[3] = {
['name'] = "Drugs", -- Name of the airdrop that will be shown in notifications
['items'] = { -- Loot table
{ItemName = "weed", ItemAmount = 10, Chance = 100, Type = "item"},
{ItemName = "coke", ItemAmountMin = 5, ItemAmountMax = 15, Chance = 50, Type = "item"},
},
},
}
-- List of blip IDs and colors - https://docs.fivem.net/docs/game-references/blips/
Config.blips = {
main = {
['enabled'] = true, -- Should the main blip be on ? (true/false)
['scale'] = 1.2, -- Scale of the main blip
['blipId'] = 568, -- Blip (See link above for reference)
['color'] = 81, -- Blip color (See link above for reference)
['type'] = 6, -- For blip types, please reference: https://docs.fivem.net/natives/?_0x9029B2F3DA924928
['name'] = "Airdrop", -- Label of the main blip on the map
},
radius = {
['enabled'] = true, -- Should the radius blip be on ? (true/false)
['color'] = 81, -- Radius blip color (See link above for reference)
['alpha'] = 100, -- Radius blip transparency (higher number = lower transparency)
},
}
Config.Marker = {
enabled = true, -- Should there be a circle marker showing how far can you go when capturing an airdrop
red = 0, green = 125, blue = 255, -- You can customize the color of the marker by adjusting RGB (0-255)
}
-- How should "collect" text be showed. Available types:
-- 0 - No 3D Text or notification will be displayed
-- 1 - 3D text is being displayed on the airdrop crate (This option is slightly less efficient, if you care about performance use another type)
-- 2 - Help notofication is being displayed in the top left corner.
-- 3 - Will run code from CustomCaptureFuntion in utils/client.lua.
-- See https://poisoncode.gitbook.io/poisoncode-docs/scripts/pc_airdrop for reference
Config.captureTextType = 1
-- [[Notifications functions has been moved to: utils/client.lua]]
-- [[Custom event has been moved to utils/client.lua]]
config/translations.lua
Click here to see a preview translations.lua
-- _____ _____ _
-- | __ \ (_) / ____| | |
-- | |__) |__ _ ___ ___ _ __ | | ___ __| | ___
-- | ___/ _ \| / __|/ _ \| '_ \| | / _ \ / _` |/ _ \
-- | | | (_) | \__ \ (_) | | | | |___| (_) | (_| | __/
-- |_| \___/|_|___/\___/|_| |_|\_____\___/ \__,_|\___|
-- © PoisonCode
-- Discord: https://discord.gg/rNJ8cHXCsN
-- Tebex: https://poisoncode.tebex.io
Translations = {
base = {
-- Text showed during airdrop capture
["collect"] = "Press ~y~E ~w~to capture the airdrop", -- Text shown before player started capturing the airdrop
["collecting"] = "Airdrop is being captured. Remaining: ~b~%s ~w~sec",
-- Used only when Config.AirdropGroundTextLabel is true
["airdrop_locked"] = "~r~Airdrop locked for: ~y~%s ~w~sec",
-- Notifications text
["notification_inbound"] = "Airdrop has been called!",
["notification_inbound_2"] = "%s airdrop was called to %s!",
["notification_startcapture"] = "You are capturing the airdrop!",
["notification_captured"] = "You captured the airdrop!",
["notification_capturecanceled"] = "You cancelled airdrop capture!",
["notification_someonecaptured"] = "Someone captured the airdrop!",
["notification_cantcapture"] = "This airdrop is already being captured!",
-- Target event label
["TargetText"] = "Capture the airdrop",
-- Ox_inventory stash label
["oxinv_label"] = "Airdrop",
},
-- Discord logs
discord = {
-- Titles
["title_auto"] = "Airdrop called automatically",
["title_command"] = "Airdrop called by command",
["title_event"] = "Airdrop called by event",
["title_captured"] = "Airdrop captured",
["title_remove"] = "Airdrop removed",
-- Desc
["call_auto"] = "Airdrop was called in automatically!",
["call_command"] = "called an airdrop using a command!",
["call_event"] = "Airdrop was called in by event!",
["captured_by"] = "Airdrop was captured by: ",
["type"] = "Type",
["location"] = "Location",
["airdrop_remove"] = "Airdrop crate was automatically removed.",
["airdrop_remove_items"] = "Airdrop crate was removed because all items were taken.",
}
}
client/utils.lua
Click here to see a preview client.lua
-- [1. Main functions]
-- a) Function responsible for sending the notifications
function SendNotification(text, type)
local time = 5000 -- how long should notification be on screen (in ms)
if Config.Use_pcnotifications then
exports['pc_notifications']:Notify(type, 'Airdrop', text, time, true)
else
-- Other notification system
end
end
-- b) Joining player sync -- EXPERIMENTAL - only works when Config.UseExperimentalFeatures is set to true
AddEventHandler('playerJoinedEvent',function()
TriggerServerEvent('pc_airdrop:server:requestAirdropSync')
end)
-- [2. Event functions]
-- a) This function is triggered when the airdrop is called
function onAirdropCall(type, location)
if Config.LocationNotification and location then
SendNotification((Translations.base["notification_inbound_2"]):format(type, location), 'info')
else
SendNotification(Translations.base["notification_inbound"], 'info')
end
-- *CUSTOM CODE*
-- *EVENT TRIGGER*
-- ETC.
end
-- b) This function is triggered when the airdrop hits the ground (Does not trigger if Config.AirdropGroundSpawn is on)
function onAirdropHit()
--SendNotification("Airdrop hit the ground!", 'info')
end
-- c) This function is triggered when the airdrop unlocks (Only when airdrop lock is enabled in Config)
function onAirdropUnlock()
--SendNotification("Airdrop has been unlocked!", 'info')
end
-- d) This function is triggered when you start capturing the airdrop
function onCaptureStart()
SendNotification(Translations.base["notification_startcapture"], 'info')
end
-- e) This function is triggered when you successfully capture the airdrop
function onAirdropCapture()
SendNotification(Translations.base["notification_captured"], 'success')
end
-- f) This function is triggered when someone else successfully captures the airdrop
function onCaptureSomeone()
SendNotification(Translations.base["notification_someonecaptured"], 'info')
end
-- g) This function is triggered when you cancel capturing the airdrop
function onCaptureCancel()
SendNotification(Translations.base["notification_capturecanceled"], 'error')
end
-- h) This function is triggered when you try to capture the airdrop but you can't
function onCaptureTryFail()
SendNotification(Translations.base["notification_cantcapture"], 'error')
end
-- [3. Integration/technical functions]
-- a) 3D Text function, you can customize font, size etc.
function Draw3DText(x, y, z, scl_factor, text)
local onScreen, _x, _y = World3dToScreen2d(x, y, z + 1.0)
local p = GetGameplayCamCoords()
local distance = GetDistanceBetweenCoords(p.x, p.y, p.z, x, y, z + 1.0, 1)
local scale = (1 / distance) * 2
local fov = (1 / GetGameplayCamFov()) * 100
local scale = scale * fov * scl_factor
if onScreen then
SetTextScale(0.0, scale)
SetTextFont(4)
SetTextProportional(1)
SetTextColour(255, 255, 255, 215)
SetTextDropshadow(0, 0, 0, 0, 255)
SetTextEdge(2, 0, 0, 0, 150)
SetTextDropShadow()
SetTextOutline()
SetTextEntry("STRING")
SetTextCentre(1)
AddTextComponentString(text)
DrawText(_x, _y)
end
end
-- b) Help Notification function, not much to customize
function ShowHelpNotification(text)
SetTextComponentFormat("STRING")
AddTextComponentString(text)
DisplayHelpTextFromStringLabel(0, 0, 1, -1)
end
-- c) Custom function that should be ran when Config.captureTextType is set to 3
function CustomCaptureFuntion(text)
print(text) -- EXAMPLE
-- You can add custom code here to for example: trigger a progress bar
end
-- d) Blips customization
function CreateBlips(coords, radius)
-- Main blip
if Config.blips.main['enabled'] then
blips[1] = AddBlipForCoord(coords)
SetBlipScale(blips[1], Config.blips.main['scale'])
SetBlipSprite(blips[1], Config.blips.main['blipId'])
SetBlipHighDetail(blips[1], true)
SetBlipColour(blips[1], Config.blips.main['color'])
SetBlipDisplay(blips[1], Config.blips.main['type'])
BeginTextCommandSetBlipName("STRING")
AddTextComponentString(Config.blips.main['name'])
EndTextCommandSetBlipName(blips[1])
end
-- Radius blip
if Config.blips.radius['enabled'] and radius then
blips[2] = AddBlipForRadius(coords, radius + 10.0)
SetBlipSprite(blips[2], 9)
SetBlipColour(blips[2], Config.blips.radius['color'])
SetBlipAlpha(blips[2], Config.blips.radius['alpha'])
end
end
-- [4. Targeting system integration]
if Config.Use_Target then
if Config.Target == "qtarget" then
exports.qtarget:AddTargetModel({GetHashKey(Config.Models.crate)}, {
options = {
{
event = "pc_airdrop:client:targetcollect",
icon = "fas fa-hand",
label = Translations.base["TargetText"],
canInteract = function()
return not capturing_me and not capturing_someone and lock_timer <= 0
end
},
},
distance = 5.0,
})
elseif Config.Target == "ox_target" then
exports.ox_target:addModel({GetHashKey(Config.Models.crate)}, {
name = 'Airdrop',
label = Translations.base["TargetText"],
icon = "fas fa-hand",
event = "pc_airdrop:client:targetcollect",
canInteract = function()
return not capturing_me and not capturing_someone and lock_timer <= 0
end,
distance = 5.0,
})
elseif Config.Target == "qb-target" then
exports['qb-target']:AddTargetModel(GetHashKey(Config.Models.crate), {
options = {
{
type = "client",
event = "pc_airdrop:client:targetcollect",
icon = "fas fa-hand",
label = Translations.base["TargetText"],
canInteract = function()
return not capturing_me and not capturing_someone and lock_timer <= 0
end
},
},
distance = 5.0,
})
end
end
server/utils.lua
Click here to see a preview server.lua
-- [1. Framework + integrations]
Framework = nil
if Config.Framework == "NEW-ESX" then
Framework = exports["es_extended"]:getSharedObject()
elseif Config.Framework == "ESX" then
TriggerEvent('esx:getSharedObject', function(library)
Framework = library
end)
elseif Config.Framework == "QBCore" then
Framework = exports["qb-core"]:GetCoreObject()
end
function RewardItems(src, item, amount, type)
-- If you're using esx:
if Config.Framework == "NEW-ESX" or Config.Framework == "ESX" then
local xPlayer = Framework.GetPlayerFromId(src)
if xPlayer then
if type ~= "weapon" then -- adding an item
xPlayer.addInventoryItem(item, amount)
-- You can add notifications here if you'd like
else -- adding a weapon
xPlayer.addWeapon(item, amount)
-- You can add notifications here if you'd like
end
end
-- if you're using qb-core:
elseif Config.Framework == "QBCore" then
local xPlayer = Framework.Functions.GetPlayer(src)
if xPlayer then
xPlayer.Functions.AddItem(item, amount)
-- You can add notifications here if you'd like
end
end
end
-- ox_inventory integration (if you're using other grid based inventory system, you can modify this part of the code)
-- don't touch it if you don't know what you're doing
if Config.Use_OxInventory then
local ox_inventory = exports.ox_inventory
ox_inventory:RegisterStash('airdrop', Translations.base["oxinv_label"], 50, 100000, false)
function oxinvAddItem(itemName, itemCount)
local inventory = ox_inventory:GetInventory({id = 'airdrop'})
ox_inventory:AddItem(inventory.id, itemName, itemCount)
end
function oxinvClearInv()
local inventory = ox_inventory:GetInventory({id = 'airdrop'})
ox_inventory:ClearInventory(inventory)
end
end
-- [2. Airdrop spawning]
-- COMMAND
-- WARNING: THIS COMMAND IS AVAILABLE FOR EVERYONE BY DEFAULT, CHANGE THE CODE BELOW TO ONLY ALLOW CERATIN PEOPLE TO CALL THE AIRDROP!
if Config.AirdropSpawnMethod['command_enabled'] then
RegisterCommand("airdrop", function(source, args, rawCommand)
createNewAirdrop({type = "command", src = source, arg = args})
end)
end
-- EVENT
-- IF SET TO TRUE IN CONFIG "pc_airdrop:server:createNewAirdrop" SERVER EVENT WILL BE CREATED
-- YOU CAN CREATE YOUR OWN WAY OF CALLING AN AIRDROP USING THIS EVENT
if Config.AirdropSpawnMethod['event_enabled'] then
RegisterNetEvent("pc_airdrop:server:createNewAirdrop", function(args)
createNewAirdrop({type = "event", src = source, arg = args})
end)
end
-- [3. Discord logs]
if Config.DiscordLogs then
WebhookURL = "" -- INSERT YOU DISCORD WEBHOOK HERE
function DiscordLog(title,desc,color)
PerformHttpRequest(WebhookURL, function(err, text, headers) end, 'POST', json.encode({
username = "Airdrop - Logs",
embeds = {{
["color"] = color,
["title"] = title,
["description"] = desc,
["footer"] = {
["text"] = "PoisonCode Airdrop • "..os.date("%x %X %p")
},
}}
}), {
['Content-Type'] = 'application/json'
})
end
end
If you encounter any problems during configuration, you can create a support ticket on our discord.
Last updated
Was this helpful?