337 lines
12 KiB
Lua
337 lines
12 KiB
Lua
|
local QBCore = exports["qb-core"]:GetCoreObject()
|
||
|
|
||
|
local Action = {
|
||
|
name = "",
|
||
|
duration = 0,
|
||
|
label = "",
|
||
|
useWhileDead = false,
|
||
|
canCancel = true,
|
||
|
disarm = true,
|
||
|
controlDisables = {
|
||
|
disableMovement = false,
|
||
|
disableCarMovement = false,
|
||
|
disableMouse = false,
|
||
|
disableCombat = false,
|
||
|
},
|
||
|
animation = {
|
||
|
animDict = nil,
|
||
|
anim = nil,
|
||
|
flags = 0,
|
||
|
task = nil,
|
||
|
},
|
||
|
prop = {
|
||
|
model = nil,
|
||
|
bone = nil,
|
||
|
coords = { x = 0.0, y = 0.0, z = 0.0 },
|
||
|
rotation = { x = 0.0, y = 0.0, z = 0.0 },
|
||
|
},
|
||
|
propTwo = {
|
||
|
model = nil,
|
||
|
bone = nil,
|
||
|
coords = { x = 0.0, y = 0.0, z = 0.0 },
|
||
|
rotation = { x = 0.0, y = 0.0, z = 0.0 },
|
||
|
},
|
||
|
}
|
||
|
|
||
|
local isDoingAction = false
|
||
|
local wasCancelled = false
|
||
|
local isAnim = false
|
||
|
local isProp = false
|
||
|
local isPropTwo = false
|
||
|
local prop_net = nil
|
||
|
local propTwo_net = nil
|
||
|
local runProgThread = false
|
||
|
|
||
|
RegisterNetEvent('progressbar:client:ToggleBusyness', function(bool)
|
||
|
isDoingAction = bool
|
||
|
end)
|
||
|
|
||
|
function ActionCleanup()
|
||
|
local ped = PlayerPedId()
|
||
|
|
||
|
if Action.animation then
|
||
|
if Action.animation.task or (Action.animation.animDict and Action.animation.anim) then
|
||
|
ClearPedSecondaryTask(ped)
|
||
|
StopAnimTask(ped, Action.animDict, Action.anim, 1.0)
|
||
|
end
|
||
|
end
|
||
|
if prop_net then
|
||
|
DetachEntity(NetToObj(prop_net), 1, 1)
|
||
|
DeleteEntity(NetToObj(prop_net))
|
||
|
prop_net = nil
|
||
|
end
|
||
|
|
||
|
if propTwo_net then
|
||
|
DetachEntity(NetToObj(propTwo_net), 1, 1)
|
||
|
DeleteEntity(NetToObj(propTwo_net))
|
||
|
propTwo_net = nil
|
||
|
end
|
||
|
|
||
|
runProgThread = false
|
||
|
end
|
||
|
|
||
|
local function Cancel()
|
||
|
TriggerEvent('progressbar:setstatus', false)
|
||
|
isDoingAction = false
|
||
|
wasCancelled = true
|
||
|
|
||
|
LocalPlayer.state:set("inv_busy", false, true) -- Not Busy
|
||
|
ActionCleanup()
|
||
|
|
||
|
SendNUIMessage({
|
||
|
action = "cancel"
|
||
|
})
|
||
|
end
|
||
|
|
||
|
local function Finish()
|
||
|
TriggerEvent('progressbar:setstatus', false)
|
||
|
isDoingAction = false
|
||
|
ActionCleanup()
|
||
|
LocalPlayer.state:set("inv_busy", false, true) -- Not Busy
|
||
|
end
|
||
|
|
||
|
local function DisableActions()
|
||
|
if Action.controlDisables.disableMouse then
|
||
|
DisableControlAction(0, 1, true) -- LookLeftRight
|
||
|
DisableControlAction(0, 2, true) -- LookUpDown
|
||
|
DisableControlAction(0, 106, true) -- VehicleMouseControlOverride
|
||
|
end
|
||
|
|
||
|
if Action.controlDisables.disableMovement then
|
||
|
DisableControlAction(0, 30, true) -- disable left/right
|
||
|
DisableControlAction(0, 31, true) -- disable forward/back
|
||
|
DisableControlAction(0, 36, true) -- INPUT_DUCK
|
||
|
DisableControlAction(0, 21, true) -- disable sprint
|
||
|
end
|
||
|
|
||
|
if Action.controlDisables.disableCarMovement then
|
||
|
DisableControlAction(0, 63, true) -- veh turn left
|
||
|
DisableControlAction(0, 64, true) -- veh turn right
|
||
|
DisableControlAction(0, 71, true) -- veh forward
|
||
|
DisableControlAction(0, 72, true) -- veh backwards
|
||
|
DisableControlAction(0, 75, true) -- disable exit vehicle
|
||
|
end
|
||
|
|
||
|
if Action.controlDisables.disableCombat then
|
||
|
DisablePlayerFiring(PlayerId(), true) -- Disable weapon firing
|
||
|
DisableControlAction(0, 24, true) -- disable attack
|
||
|
DisableControlAction(0, 25, true) -- disable aim
|
||
|
DisableControlAction(1, 37, true) -- disable weapon select
|
||
|
DisableControlAction(0, 47, true) -- disable weapon
|
||
|
DisableControlAction(0, 58, true) -- disable weapon
|
||
|
DisableControlAction(0, 140, true) -- disable melee
|
||
|
DisableControlAction(0, 141, true) -- disable melee
|
||
|
DisableControlAction(0, 142, true) -- disable melee
|
||
|
DisableControlAction(0, 143, true) -- disable melee
|
||
|
DisableControlAction(0, 263, true) -- disable melee
|
||
|
DisableControlAction(0, 264, true) -- disable melee
|
||
|
DisableControlAction(0, 257, true) -- disable melee
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function loadAnimDict(dict)
|
||
|
if not HasAnimDictLoaded(dict) then
|
||
|
while not HasAnimDictLoaded(dict) do
|
||
|
RequestAnimDict(dict)
|
||
|
Wait(25)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function loadModel(model)
|
||
|
if not HasModelLoaded(model) then
|
||
|
while not HasModelLoaded(model) do
|
||
|
RequestModel(model)
|
||
|
Wait(25)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function ActionStart()
|
||
|
runProgThread = true
|
||
|
LocalPlayer.state:set("inv_busy", true, true) -- Busy
|
||
|
|
||
|
CreateThread(function()
|
||
|
while runProgThread do
|
||
|
if isDoingAction then
|
||
|
if not isAnim then
|
||
|
if Action.animation then
|
||
|
if Action.animation.task then
|
||
|
TaskStartScenarioInPlace(PlayerPedId(), Action.animation.task, 0, true)
|
||
|
elseif Action.animation.animDict and Action.animation.anim then
|
||
|
if Action.animation.flags == nil then
|
||
|
Action.animation.flags = 1
|
||
|
end
|
||
|
|
||
|
local player = PlayerPedId()
|
||
|
if (DoesEntityExist(player) and not IsEntityDead(player)) then
|
||
|
loadAnimDict( Action.animation.animDict)
|
||
|
TaskPlayAnim(player, Action.animation.animDict, Action.animation.anim, 3.0, 3.0, -1, Action.animation.flags, 0, 0, 0, 0 )
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
isAnim = true
|
||
|
end
|
||
|
if not isProp and Action.prop and Action.prop.model then
|
||
|
loadModel(joaat(Action.prop.model))
|
||
|
|
||
|
local pCoords = GetOffsetFromEntityInWorldCoords(PlayerPedId(), 0.0, 0.0, 0.0)
|
||
|
local modelSpawn = CreateObject(joaat(Action.prop.model), pCoords.x, pCoords.y, pCoords.z, true, true, true)
|
||
|
|
||
|
local netid = ObjToNet(modelSpawn)
|
||
|
SetNetworkIdExistsOnAllMachines(netid, true)
|
||
|
NetworkSetNetworkIdDynamic(netid, true)
|
||
|
SetNetworkIdCanMigrate(netid, false)
|
||
|
if Action.prop.bone == nil then
|
||
|
Action.prop.bone = 60309
|
||
|
end
|
||
|
|
||
|
if Action.prop.coords == nil then
|
||
|
Action.prop.coords = { x = 0.0, y = 0.0, z = 0.0 }
|
||
|
end
|
||
|
|
||
|
if Action.prop.rotation == nil then
|
||
|
Action.prop.rotation = { x = 0.0, y = 0.0, z = 0.0 }
|
||
|
end
|
||
|
|
||
|
AttachEntityToEntity(modelSpawn, PlayerPedId(), GetPedBoneIndex(PlayerPedId(), Action.prop.bone), Action.prop.coords.x, Action.prop.coords.y, Action.prop.coords.z, Action.prop.rotation.x, Action.prop.rotation.y, Action.prop.rotation.z, 1, 1, 0, 1, 0, 1)
|
||
|
prop_net = netid
|
||
|
|
||
|
isProp = true
|
||
|
|
||
|
if not isPropTwo and Action.propTwo and Action.propTwo.model then
|
||
|
loadModel(joaat(Action.propTwo.model))
|
||
|
|
||
|
local pCoords2 = GetOffsetFromEntityInWorldCoords(PlayerPedId(), 0.0, 0.0, 0.0)
|
||
|
local modelSpawn2 = CreateObject(joaat(Action.propTwo.model), pCoords2.x, pCoords2.y, pCoords2.z, true, true, true)
|
||
|
|
||
|
local netid2 = ObjToNet(modelSpawn2)
|
||
|
SetNetworkIdExistsOnAllMachines(netid2, true)
|
||
|
NetworkSetNetworkIdDynamic(netid2, true)
|
||
|
SetNetworkIdCanMigrate(netid2, false)
|
||
|
if Action.propTwo.bone == nil then
|
||
|
Action.propTwo.bone = 60309
|
||
|
end
|
||
|
|
||
|
if Action.propTwo.coords == nil then
|
||
|
Action.propTwo.coords = { x = 0.0, y = 0.0, z = 0.0 }
|
||
|
end
|
||
|
|
||
|
if Action.propTwo.rotation == nil then
|
||
|
Action.propTwo.rotation = { x = 0.0, y = 0.0, z = 0.0 }
|
||
|
end
|
||
|
|
||
|
AttachEntityToEntity(modelSpawn2, PlayerPedId(), GetPedBoneIndex(PlayerPedId(), Action.propTwo.bone), Action.propTwo.coords.x, Action.propTwo.coords.y, Action.propTwo.coords.z, Action.propTwo.rotation.x, Action.propTwo.rotation.y, Action.propTwo.rotation.z, 1, 1, 0, 1, 0, 1)
|
||
|
propTwo_net = netid2
|
||
|
|
||
|
isPropTwo = true
|
||
|
end
|
||
|
end
|
||
|
|
||
|
DisableActions(PlayerPedId())
|
||
|
end
|
||
|
Wait(0)
|
||
|
end
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
local function Process(action, start, tick, finish)
|
||
|
ActionStart()
|
||
|
Action = action
|
||
|
if Action.icon then
|
||
|
if QBCore.Shared.Items[tostring(Action.icon)] then
|
||
|
local img = "nui://ps-inventory/html/" -- default qb-core inventory link
|
||
|
if not string.find(QBCore.Shared.Items[tostring(Action.icon)].image, "http") then -- 👀 Slipped in support for custom html links too
|
||
|
if not string.find(QBCore.Shared.Items[tostring(Action.icon)].image, "images/") then --search for if the icon images have /images in the listing
|
||
|
img = img.."images/"
|
||
|
end
|
||
|
Action.icon = img..QBCore.Shared.Items[tostring(Action.icon)].image
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
if not IsEntityDead(PlayerPedId()) or Action.useWhileDead then
|
||
|
if not isDoingAction then
|
||
|
isDoingAction = true
|
||
|
wasCancelled = false
|
||
|
isAnim = false
|
||
|
isProp = false
|
||
|
TriggerEvent('progressbar:setstatus', true)
|
||
|
SendNUIMessage({
|
||
|
action = "progress",
|
||
|
duration = Action.duration,
|
||
|
label = Action.label,
|
||
|
icon = Action.icon
|
||
|
})
|
||
|
CreateThread(function ()
|
||
|
if start then
|
||
|
start()
|
||
|
end
|
||
|
while isDoingAction do
|
||
|
Wait(1)
|
||
|
if tick then
|
||
|
tick()
|
||
|
end
|
||
|
if IsControlJustPressed(0, 177) and Action.canCancel then -- IsControlJustPressed(0, 177) BACKSPACE
|
||
|
TriggerEvent("progressbar:client:cancel")
|
||
|
end
|
||
|
|
||
|
if IsEntityDead(PlayerPedId()) and not Action.useWhileDead then
|
||
|
TriggerEvent("progressbar:client:cancel")
|
||
|
end
|
||
|
end
|
||
|
if finish then
|
||
|
finish(wasCancelled)
|
||
|
end
|
||
|
end)
|
||
|
else
|
||
|
TriggerEvent("QBCore:Notify", "Du er allerede igang med noget!", "error")
|
||
|
end
|
||
|
else
|
||
|
TriggerEvent("QBCore:Notify", "Det kan du ikke!", "error")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
RegisterNetEvent("progressbar:client:progress", function(action, finish)
|
||
|
Process(action, nil, nil, finish)
|
||
|
end)
|
||
|
|
||
|
RegisterNetEvent("progressbar:client:ProgressWithStartEvent", function(action, start, finish)
|
||
|
Process(action, start, nil, finish)
|
||
|
end)
|
||
|
|
||
|
RegisterNetEvent("progressbar:client:ProgressWithTickEvent", function(action, tick, finish)
|
||
|
Process(action, nil, tick, finish)
|
||
|
end)
|
||
|
|
||
|
RegisterNetEvent("progressbar:client:ProgressWithStartAndTick", function(action, start, tick, finish)
|
||
|
Process(action, start, tick, finish)
|
||
|
end)
|
||
|
|
||
|
RegisterNetEvent("progressbar:client:cancel", function()
|
||
|
Cancel()
|
||
|
end)
|
||
|
|
||
|
RegisterNUICallback('FinishAction', function(_, cb)
|
||
|
Finish()
|
||
|
cb("ok")
|
||
|
end)
|
||
|
|
||
|
|
||
|
local function Progress(action, finish)
|
||
|
Process(action, nil, nil, finish)
|
||
|
end exports("Progress", Progress)
|
||
|
|
||
|
local function ProgressWithStartEvent(action, start, finish)
|
||
|
Process(action, start, nil, finish)
|
||
|
end exports("ProgressWithStartEvent", ProgressWithStartEvent)
|
||
|
|
||
|
local function ProgressWithTickEvent(action, tick, finish)
|
||
|
Process(action, nil, tick, finish)
|
||
|
end exports("ProgressWithTickEvent", ProgressWithTickEvent)
|
||
|
|
||
|
local function ProgressWithStartAndTick(action, start, tick, finish)
|
||
|
Process(action, start, tick, finish)
|
||
|
end exports("ProgressWithStartAndTick", ProgressWithStartAndTick)
|