local ESX = nil local QBCore = nil local PlayerData = nil if GetResourceState('es_extended') == 'started' then ESX = exports['es_extended']:getSharedObject() PlayerData = ESX.GetPlayerData() RegisterNetEvent('esx:playerLoaded', function(xPlayer) PlayerData = xPlayer end) RegisterNetEvent('esx:setJob', function(job) PlayerData.job = job end) elseif GetResourceState('qb-core') == 'started' then QBCore = exports['qb-core']:GetCoreObject() PlayerData = QBCore.Functions.GetPlayerData() RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function() PlayerData = QBCore.Functions.GetPlayerData() end) RegisterNetEvent('QBCore:Client:OnJobUpdate', function(job) PlayerData.job = job end) end Functions = {} -- This function should return the player's job, adjust to your framework if required Functions.GetPlayerJob = function() if (GetResourceState('es_extended') == 'started' and PlayerData) then return PlayerData.job.name elseif (GetResourceState('qb-core') == 'started' and PlayerData) then return PlayerData.job.name end return 'unemployed' end -- A general notification, you can use your own notification system here as well Functions.Notify = function(message) if (message == nil or message == '') then return end BeginTextCommandThefeedPost('STRING') AddTextComponentSubstringPlayerName(message) EndTextCommandThefeedPostTicker(false, true) end -- This function should return wether the player is dead or not, adjust to your death-system Functions.IsPlayerDead = function() -- If wasabi_ambulance is used, this will handle the death check if GetResourceState('wasabi_ambulance') == 'started' then return exports.wasabi_ambulance:isPlayerDead() end local ped = PlayerPedId() if (IsPedDeadOrDying(ped, true)) then return true end return false end -- This function should return if the player can interact with third-eye or not, adjust to your needs Functions.CanInteract = function() local ped = PlayerPedId() local isPedInVehicle = IsPedInAnyVehicle(ped, false) local isPedDead = Functions.IsPlayerDead() if (isPedInVehicle or isPedDead) then return false end return true end -- This function should return if the vehicle can be interacted with or not, adjust to your needs Functions.CanInteractWithVehicle = function(entity) -- Check if the trunk of the vehicle is open if GetVehicleDoorAngleRatio(entity, 5) > 0 then return true end return false end -- This function adds the required target-option to vehicles, ox-target and qb-target are supported by default but you can add your own target-option if you want to use another target-system Functions.AddGlobalTargetOptions = function() -- For the people ussing ox-target if (GetResourceState('ox_target') == 'started') then exports.ox_target:addGlobalVehicle({ { icon = 'fas fa-expand', label = Config.Target.Trunk.Label, distance = Config.Target.Trunk.InteractDistance, groups = Config.Target.Trunk.GlobalJobRequirement.Enabled and Config.Target.Trunk.GlobalJobRequirement.Names or nil, bones = { 'boot' }, onSelect = function(data) ViewVehicleTrunk(data.entity) end, canInteract = function(entity) return (Functions.CanInteract() and Functions.CanInteractWithVehicle(entity) and Entity(entity).state.TrunkPropsFromState ~= nil and not isCarryingProp) end }, }) return end -- For the people using qb-target if (GetResourceState('qb-target') == 'started') then exports['qb-target']:AddTargetBone('boot', { options = { { icon = 'fas fa-expand', label = Config.Target.Trunk.Label, job = Config.Target.Trunk.GlobalJobRequirement.Enabled and Config.Target.Trunk.GlobalJobRequirement.Names or nil, action = function(entity) ViewVehicleTrunk(entity) end, canInteract = function(entity) return (Functions.CanInteract() and Functions.CanInteractWithVehicle(entity) and Entity(entity).state.TrunkPropsFromState ~= nil and not isCarryingProp) end, }, }, distance = Config.Target.Trunk.InteractDistance, }) return end print('gs_advancedtrunk: [ERROR] No target interaction defined') end --- --- All Trunk related bridge functions are defined next --- -- Add any additional code here that you want to run when the trunk is opened Functions.OnTrunkOpen = function(vehicle) -- Removes the radar from the player UI DisplayRadar(false) -- Disable targeting when the trunk is open if (GetResourceState('ox_target') == 'started') then exports.ox_target:disableTargeting(true) elseif (GetResourceState('qb-target') == 'started') then exports['qb-target']:AllowTargeting(false) end -- Some help-text is displayed with this export if ox_lib is used if (GetResourceState('ox_lib') == 'started' and Config.UseKeyboardForSelection) then exports.ox_lib:showTextUI('[A/D] Move selection - [ENTER] Confirm - [BACKSPACE] Cancel', { position = "bottom-center", icon = 'fas fa-up-down-left-right', style = { color = 'white' } }) end end -- Add any additional code here that you want to run when the trunk is closed Functions.OnTrunkClose = function(vehicle) -- Adds back the radar from the player UI DisplayRadar(true) -- Enable targeting when the trunk is closed if (GetResourceState('ox_target') == 'started') then exports.ox_target:disableTargeting(false) elseif (GetResourceState('qb-target') == 'started') then exports['qb-target']:AllowTargeting(true) end -- Hides the help-text if ox_lib is used if (GetResourceState('ox_lib') == 'started' and Config.UseKeyboardForSelection) then exports.ox_lib:hideTextUI() end end -- This code runs every frame when the trunk is open, adjust to your needs Functions.OnTrunkTick = function(vehicle) -- Disable controls to prevent the player from moving DisableControlAction(0, 22, true) -- SPACE (Jump) DisableControlAction(0, 23, true) -- F (Enter vehicle) DisableControlAction(0, 24, true) -- LMB (Attack) DisableControlAction(0, 30, true) -- D (INPUT_MOVE_LR) DisableControlAction(0, 31, true) -- S (INPUT_MOVE_UD) DisableControlAction(0, 36, true) -- L-CTRL (Duck) DisableControlAction(0, 44, true) -- Q (Cover) DisableControlAction(0, 140, true) -- R (INPUT_MELEE_ATTACK_LIGHT) end -- This function should return if the trunk should close or not (for instance if the player dies), adjust to your needs Functions.ShouldTrunkClose = function(vehicle) -- Check if the trunk is closed if GetVehicleDoorAngleRatio(vehicle, 5) == 0 then return true end -- Check if the player is dead local isPedDead = Functions.IsPlayerDead() if isPedDead then return true end -- Check if the vehicle is to far away from the player local ped = PlayerPedId() local pedCoords = GetEntityCoords(ped) local vehicleCoords = GetEntityCoords(vehicle) local distance = #(pedCoords - vehicleCoords) if (distance > Config.Target.Trunk.InteractDistance + 3.0) then return true end return false end --- --- All Prop walking related bridge functions are defined next --- -- This function is triggered right before someone starts walking with a prop Functions.OnWalkWithProp = function(prop, canPlaceProp) -- Some help-text is displayed with this export if ox_lib is used if (GetResourceState('ox_lib') == 'started') then local text = canPlaceProp and '[ENTER] Place - [BACKSPACE] Cancel' or '[BACKSPACE] Cancel' exports.ox_lib:showTextUI(text, { position = "bottom-center", icon = 'fas fa-up-down-left-right', style = { color = 'white' } }) end end -- This function is triggered right after someone stops walking with a prop Functions.OnStopWalkWithProp = function(prop) -- Hides the help-text if ox_lib is used if (GetResourceState('ox_lib') == 'started') then exports.ox_lib:hideTextUI() end end -- This code runs every frame when the player is walking with a prop, adjust to your needs Functions.OnWalkWithPropTick = function(prop) -- Disable certain controls DisableControlAction(0, 22, true) -- SPACE (Jump) DisableControlAction(0, 23, true) -- F (Enter vehicle) DisableControlAction(0, 24, true) -- LMB (Attack) DisableControlAction(0, 36, true) -- L-CTRL (Duck) DisableControlAction(0, 44, true) -- Q (Cover) DisableControlAction(0, 140, true) -- R (INPUT_MELEE_ATTACK_LIGHT) end -- This function adds the required target-option to remove a placed object, ox-target and qb-target are supported by default but you can add your own target-option if you want to use another target-system Functions.AddObjectTargets = function(prop, propName) -- For the people ussing ox-target if (GetResourceState('ox_target') == 'started') then local options = { { icon = 'fas fa-trash-can', label = Config.Target.Object.LabelRemove, distance = Config.Target.Object.InteractDistance, groups = RequiredJobsToPickupOrRemove or nil, onSelect = function(data) PlayAnimation(Config.WalkWithProp[propName].PickupAnimDict, Config.WalkWithProp[propName].PickupAnimName, Config.WalkWithProp[propName].PickupAnimFlag, Config.WalkWithProp[propName].PickupAnimTime) while IsEntityPlayingAnim(PlayerPedId(), Config.WalkWithProp[propName].PickupAnimDict, Config.WalkWithProp[propName].PickupAnimName, 3) do Wait(0) end if (not DoesEntityExist(data.entity)) then return end local propNetId = NetworkGetNetworkIdFromEntity(data.entity) TriggerServerEvent('gs_advancedtrunk:RemoveProp', propNetId) end, canInteract = function(entity) return (Functions.CanInteract() and not isCarryingProp) end }, } if Config.WalkWithProp[propName].CanPickUp then table.insert(options, { icon = 'fas fa-hand-spock', label = Config.Target.Object.LabelPickup, distance = Config.Target.Object.InteractDistance, groups = RequiredJobsToPickupOrRemove or nil, onSelect = function(data) PlayAnimation(Config.WalkWithProp[propName].PickupAnimDict, Config.WalkWithProp[propName].PickupAnimName, Config.WalkWithProp[propName].PickupAnimFlag, Config.WalkWithProp[propName].PickupAnimTime) while IsEntityPlayingAnim(PlayerPedId(), Config.WalkWithProp[propName].PickupAnimDict, Config.WalkWithProp[propName].PickupAnimName, 3) do Wait(0) end if (not DoesEntityExist(data.entity)) then return end local propNetId = NetworkGetNetworkIdFromEntity(data.entity) TriggerServerEvent('gs_advancedtrunk:RemoveProp', propNetId) Actions.WalkWithProp(propName) end, canInteract = function(entity) return (Functions.CanInteract() and not isCarryingProp) end }) end exports.ox_target:addLocalEntity(prop, options) return end -- For the people using qb-target if (GetResourceState('qb-target') == 'started') then local options = { { icon = 'fas fa-trash-can', label = Config.Target.Object.LabelRemove, job = RequiredJobsToPickupOrRemove or nil, action = function(entity) PlayAnimation(Config.WalkWithProp[propName].PickupAnimDict, Config.WalkWithProp[propName].PickupAnimName, Config.WalkWithProp[propName].PickupAnimFlag, Config.WalkWithProp[propName].PickupAnimTime) while IsEntityPlayingAnim(PlayerPedId(), Config.WalkWithProp[propName].PickupAnimDict, Config.WalkWithProp[propName].PickupAnimName, 3) do Wait(0) end if (not DoesEntityExist(entity)) then return end local propNetId = NetworkGetNetworkIdFromEntity(entity) TriggerServerEvent('gs_advancedtrunk:RemoveProp', propNetId) end, canInteract = function(entity) return (Functions.CanInteract() and not isCarryingProp) end, }, } if Config.WalkWithProp[propName].CanPickUp then table.insert(options, { icon = 'fas fa-hand-spock', label = Config.Target.Object.LabelPickup, job = RequiredJobsToPickupOrRemove or nil, action = function(entity) PlayAnimation(Config.WalkWithProp[propName].PickupAnimDict, Config.WalkWithProp[propName].PickupAnimName, Config.WalkWithProp[propName].PickupAnimFlag, Config.WalkWithProp[propName].PickupAnimTime) while IsEntityPlayingAnim(PlayerPedId(), Config.WalkWithProp[propName].PickupAnimDict, Config.WalkWithProp[propName].PickupAnimName, 3) do Wait(0) end if (not DoesEntityExist(entity)) then return end local propNetId = NetworkGetNetworkIdFromEntity(entity) TriggerServerEvent('gs_advancedtrunk:RemoveProp', propNetId) Actions.WalkWithProp(propName) end, canInteract = function(entity) return (Functions.CanInteract() and not isCarryingProp) end, }) end exports['qb-target']:AddTargetEntity(prop, { options = options, distance = Config.Target.Object.InteractDistance, }) return end print('gs_advancedtrunk: [ERROR] No target interaction defined') end